Spring’s content negotiation and Jackson message converters can absolutely produce 406 and 415 errors, and they do so in distinct, predictable situations: a 415 Unsupported Media Type means the request’s Content-Type header doesn’t match what the converter can read, while a 406 Not Acceptable means the response’s Content-Type can’t satisfy the Accept header. These errors are the framework’s way of saying the client and server disagree on the format of the data being exchanged, and fixing them usually involves aligning your request headers, your Spring configuration, or both.
Formula
This calculator computes your average pace and speed for a given distance and time. The formulas are:
- Pace (min/km) = Total time (minutes) ÷ Distance (km)
- Speed (km/h) = Distance (km) ÷ (Total time (minutes) ÷ 60)
Variables:
t– total time in minutes (input, e.g., 50 min)d– distance in kilometers (input, e.g., 10 km)pace– average pace in minutes per kilometer (output, 2 decimal places)speed– average speed in kilometers per hour (output, 2 decimal places)
Worked Example
Using the default values: t = 50 minutes, d = 10 km.
- Pace = 50 ÷ 10 = 5.00 min/km
- Speed = 10 ÷ (50 ÷ 60) = 10 ÷ 0.8333 = 12.00 km/h
So your average pace is 5 minutes per kilometer, and your average speed is 12 kilometers per hour. The calculator rounds to two decimal places for both outputs.
Why These Errors Occur in Spring
Spring MVC uses a chain of HttpMessageConverter implementations to serialize and deserialize request and response bodies. For JSON, that’s typically MappingJackson2HttpMessageConverter (or the newer MappingJackson2HttpMessageConverter from Spring 6). When a request comes in with a Content-Type header, Spring tries to find a converter that can read that media type. If none exists, it throws HttpMediaTypeNotSupportedException, which results in a 415 response. Similarly, when building a response, Spring looks at the Accept header and tries to find a converter that can write one of the accepted media types. If none matches, it throws HttpMediaTypeNotAcceptableException, leading to a 406.
The most common scenario for 415 is sending a request with Content-Type: text/plain to a controller method that expects @RequestBody SomeJsonObject. The Jackson converter only supports application/json, application/*+json, and a few others (like application/json-patch+json). For 406, the typical case is a client sending Accept: application/xml while the server only has Jackson (JSON) on the classpath – no XML converter is registered, so Spring can’t produce XML.
How Content Negotiation Works
Content negotiation is the process of deciding which representation of a resource to send to a client. Spring supports three strategies:
- Header-based – using the
Acceptrequest header (default). - Parameter-based – using a query parameter like
?format=json(enabled viaContentNegotiationConfigurer). - Path extension-based – using the file extension like
.json(deprecated in Spring 5, removed in Spring 6).
When a controller method returns an object, Spring consults the configured ContentNegotiationManager to determine the media type(s) the client will accept. It then picks the first converter that can write that type. If the client sends no Accept header, Spring defaults to application/json (if Jackson is present) or application/xml (if JAXB is present).
Common Causes of 415 Errors
- Wrong Content-Type header – e.g., posting JSON with
Content-Type: text/plain. Fix: setContent-Type: application/json. - Missing Jackson dependency – if you only have Spring MVC without
jackson-databind, no JSON converter exists. Add the dependency. - Custom converter not registered – if you write a custom converter for a custom media type, you must register it via
WebMvcConfigurer.configureMessageConverters(). - Controller method doesn’t have @RequestBody – if you’re trying to send a body but the method doesn’t have
@RequestBody, Spring won’t try to deserialize, but the body is ignored. That’s not a 415, but a common confusion.
Common Causes of 406 Errors
- Accept header includes an unsupported type – e.g.,
Accept: application/xmlbut no XML converter. Fix: either add an XML converter (e.g., Jackson XML module) or remove the header. - Accept header is too restrictive – e.g.,
Accept: application/json;q=0.5but the converter producesapplication/jsonwith a different quality? Actually, quality values are respected, but if the only supported type isapplication/jsonand the client only acceptsapplication/xml, you get 406. - Return type is String – if a controller returns a
String, Spring usesStringHttpMessageConverterwhich producestext/plain. If the client only acceptsapplication/json, you’ll get 406. Wrap the string in a POJO or use@ResponseBodywith a proper object. - ContentNegotiationManager misconfigured – if you’ve customized the manager to ignore the Accept header, you might get 406 when the client expects a different format.
How to Fix These Errors
- Check the request headers – Use browser dev tools or curl to see exactly what Content-Type and Accept headers are being sent. Often the client is sending the wrong one.
- Verify Jackson is on the classpath – If you’re using Spring Boot,
spring-boot-starter-webincludes Jackson. In plain Spring, addjackson-databind. - Configure converters explicitly – In a
@Configurationclass implementingWebMvcConfigurer, overrideconfigureMessageConvertersorextendMessageConvertersto add or reorder converters. - For 406, adjust the Accept header – If you control the client, set
Accept: application/json. If you don’t, you can ignore the header by configuring the content negotiation strategy to favor a fixed type. - For 415, set Content-Type correctly – If you’re using curl, add
-H "Content-Type: application/json". If you’re using fetch, set the header in the options.
Jackson Message Converter Details
The MappingJackson2HttpMessageConverter (or MappingJackson2HttpMessageConverter in Spring 6) supports the following media types by default:
application/jsonapplication/*+json(e.g.,application/hal+json)application/json-patch+json(for PATCH operations)
It can read and write any Java object that Jackson can serialize/deserialize. The converter also respects the @JsonView annotation and can handle polymorphic types. If you need to support application/xml, you must add the jackson-dataformat-xml dependency and register MappingJackson2XmlHttpMessageConverter. If you need to support text/csv, you’d need a custom converter.
Frequently Asked Questions
Why do I get 406 when I return a String?
Because StringHttpMessageConverter produces text/plain by default. If your client sends Accept: application/json, Spring can’t find a converter that writes JSON from a String. Solution: return a POJO (e.g., Map or a custom class) instead of a raw String, or annotate the method with @ResponseBody and use a wrapper object.
Can I make Spring ignore the Accept header?
Yes. In your WebMvcConfigurer, you can configure the ContentNegotiationManager to ignore the Accept header and always produce a specific media type. For example, configurer.defaultContentType(MediaType.APPLICATION_JSON); configurer.ignoreAcceptHeader(true);. This is common for APIs that only support JSON.
What’s the difference between 406 and 415 in plain terms?
415 means the server doesn’t understand the format of the request body (the Content-Type is wrong or unsupported). 406 means the server can’t produce a response in a format the client accepts (the Accept header is wrong or unsupported). Think of it as: 415 is about what you’re sending, 406 is about what you want back.
How do I add XML support to my Spring Boot app?
Add the jackson-dataformat-xml dependency to your pom.xml or build.gradle. Spring Boot will automatically register the XML converter. Then, if a client sends Accept: application/xml, Spring will return XML. You may also need to annotate your POJOs with JAXB annotations (like @XmlRootElement) for proper serialization.
Why does my controller return 406 when I have Jackson on the classpath?
Often because the controller method returns a String or a ResponseEntity with a String body. The JSON converter can’t serialize a plain String to JSON (it actually can, but it produces a JSON string, not an object). More likely, the Accept header is set to application/xml or something else. Check the exact Accept header and the converter’s supported media types.
Can I customize the error response for 406/415?
Yes. You can use @ControllerAdvice with @ExceptionHandler for HttpMediaTypeNotSupportedException and HttpMediaTypeNotAcceptableException. This lets you return a custom JSON error body instead of the default Spring error page.
Related
Formula used
in t | Finish time | min | 50 | 0 in d | Distance | km | 10 | 0 | 100000 out pace | Average pace | min/km | t / d | 2 out speed | Average speed | km/h | d / (t / 60) | 2
Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Delete Picture Kik? How to Remove Photos
- How to Stop WordPress Comment Spam: A Layered Guide
- What Happens to X Replies, DMs, and Followers After Deletion?
- Data Breaches That Shook the World
- Disable Google Assistant: Turn It Off on Android & Home
- Resin vs FDM Printers for Miniatures: Detail, Durability, Cost