The Content-Type header sent by your client is not recognized by the Spring Boot application’s message converters, preventing it from deserializing your request body.

Common Causes and Fixes

1. Incorrect Content-Type Header in Client Request

  • Diagnosis: Inspect the Content-Type header in the outgoing HTTP request from your client (e.g., using browser developer tools, curl -v, or a proxy like Charles). Common mistakes include typos, using the wrong MIME type (e.g., application/json instead of application/xml), or forgetting it entirely.
  • Fix: Ensure the Content-Type header exactly matches one of the supported types by your HttpMessageConverter implementations. For JSON, this is typically application/json.
    curl -X POST \
      http://localhost:8080/api/resource \
      -H 'Content-Type: application/json' \
      -d '{"key": "value"}'
    
  • Why it works: Spring Boot uses the Content-Type header to select the appropriate HttpMessageConverter (like MappingJackson2HttpMessageConverter for JSON) to deserialize the request body. If the header is missing or incorrect, no converter can be found.

2. Missing Jackson Dependency for JSON

  • Diagnosis: If you’re expecting to send JSON but are getting this error, you might have forgotten to include the Jackson Databind dependency, which is essential for JSON processing in Spring Boot.
  • Fix: Add the jackson-databind dependency to your pom.xml (Maven) or build.gradle (Gradle).
    • Maven:
      <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
      </dependency>
      
    • Gradle:
      implementation 'com.fasterxml.jackson.core:jackson-databind'
      
  • Why it works: Spring Boot auto-configures Jackson’s MappingJackson2HttpMessageConverter when this dependency is present, enabling it to handle application/json requests.

3. Custom HttpMessageConverter Not Registered or Configured Incorrectly

  • Diagnosis: If you’ve implemented a custom HttpMessageConverter (e.g., for a specific binary format or a less common text format), verify that it’s properly registered with Spring and that its canRead method correctly identifies the Content-Type it handles.
  • Fix: Ensure your custom converter is registered as a Spring @Bean or that it’s included in the list of converters managed by WebMvcConfigurer.
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
            converters.add(new MyCustomHttpMessageConverter());
        }
    }
    
    Make sure your MyCustomHttpMessageConverter’s canRead(Class<?> clazz, MediaType mediaType) method returns true for the MediaType you are sending.
  • Why it works: Spring Boot’s MVC configuration needs to be aware of any custom converters you provide so it can consider them when matching Content-Type headers.

4. Incorrect Accept Header vs. Content-Type Header

  • Diagnosis: While Content-Type dictates how the request body should be interpreted, the Accept header tells the server what response format the client expects. A mismatch here isn’t the direct cause of "Media Type Not Supported" for the request, but it can lead to confusion or subsequent errors if the server tries to match response types incorrectly. The error message specifically points to the incoming Content-Type.
  • Fix: Ensure your client sends a Content-Type that matches the data you are sending. The Accept header should specify what you want in return (e.g., Accept: application/json).
    curl -X POST \
      http://localhost:8080/api/resource \
      -H 'Content-Type: application/json' \
      -H 'Accept: application/json' \
      -d '{"key": "value"}'
    
  • Why it works: This separates the concerns of request body deserialization (Content-Type) from response body serialization (Accept), ensuring both parts of the HTTP interaction are correctly handled.

5. Content-Type Mismatch with Controller @RequestMapping consumes Attribute

  • Diagnosis: If your controller method has a consumes attribute specified in its @RequestMapping or @PostMapping annotation, Spring requires the incoming Content-Type to match one of the specified types.
  • Fix: Update the consumes attribute to include the Content-Type your client is sending, or adjust your client’s Content-Type header to match the consumes attribute.
    @PostMapping(value = "/data", consumes = "application/vnd.mycompany.v1+json")
    public ResponseEntity<?> processData(@RequestBody MyObject data) {
        // ...
    }
    
    If your client is sending application/json, change the consumes attribute to:
    @PostMapping(value = "/data", consumes = "application/json")
    public ResponseEntity<?> processData(@RequestBody MyObject data) {
        // ...
    }
    
  • Why it works: The consumes attribute acts as a filter, ensuring that the controller method is only invoked for requests with a matching Content-Type, preventing ambiguous routing and ensuring the correct deserialization logic is applied.

6. Spring Boot Version Compatibility Issues with Message Converters

  • Diagnosis: In very rare cases, particularly with significant upgrades or when mixing custom configurations with older Spring Boot starters, there might be subtle incompatibilities in how message converters are auto-configured or registered.
  • Fix: Ensure your Spring Boot version is up-to-date and that you are using the standard starters (spring-boot-starter-web). If you have a custom WebMvcConfigurer or WebMvcRegistrations, review its implementation for any deprecated methods or incorrect overrides that might interfere with default converter registration.
  • Why it works: Standard Spring Boot starters provide well-tested configurations for common message types. Deviations from this or outdated configurations can lead to unexpected behavior in the message conversion pipeline.

The next error you’ll likely encounter after resolving this is a HttpMessageNotReadableException if the request body itself is malformed according to the Content-Type (e.g., invalid JSON syntax).

Want structured learning?

Take the full Spring-boot course →