Handling Missing Content-Type Header in Spring Boot REST APIs

When building REST APIs in Spring Boot, developers often rely on Spring’s powerful annotation-based request mapping to validate incoming HTTP headers automatically. Usually, when a required header like authToken or Protocol-Version is missing, the framework throws a MissingRequestHeaderException, which can be cleanly handled with a global @ExceptionHandler.

However, one header often behaves differently — the Content-Type.


The Problem: Content-Type Doesn’t Trigger MissingRequestHeaderException

You might define a @PostMapping endpoint like this:

@PostMapping("/{payment-product}")
public ResponseEntity<GenericResponse<Object>> createPayment(
        @RequestHeader("authToken") String authToken,
        @RequestHeader("Protocol-Version") String protocolVersion,
        @RequestHeader("Content-Type") String contentType,
        @RequestBody PaymentRequestBody paymentRequest) {
    // ...
}

For most headers, missing values trigger a MissingRequestHeaderException, which can be caught and handled by an exception handler such as:

@ExceptionHandler({MissingRequestHeaderException.class, MissingPathVariableException.class})
public ResponseEntity<Object> handleBadRequest(Exception exception) {
    return ResponseEntity.status(HttpStatus.BAD_REQUEST)
            .body(new GenericResponse<>()
                    .withStatus(HttpStatus.BAD_REQUEST)
                    .withMessage("Missing parameters in the header or path"));
}

But when the Content-Type header is not provided, the framework does not raise a MissingRequestHeaderException. Instead, Spring intercepts the request before it reaches your controller, resulting in no handler being executed.


Why Spring Treats Content-Type Differently

The Content-Type header is a special HTTP header that defines how Spring should parse the request body.

If it’s missing or set incorrectly, Spring’s message converter layer throws a different type of exception — often an HttpMediaTypeNotSupportedException or HttpMessageNotReadableException.

This happens before the controller method is invoked, which explains why your @ExceptionHandler(MissingRequestHeaderException.class) doesn’t catch it.


How to Return a 400 Error When Content-Type Is Missing

To ensure your API returns a consistent 400 Bad Request when Content-Type is missing, you can extend your global exception handling strategy.

Here’s how to update your controller advice:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler({
        MissingRequestHeaderException.class,
        MissingPathVariableException.class,
        HttpMediaTypeNotSupportedException.class
    })
    public ResponseEntity<Object> handleBadRequest(Exception exception) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(new GenericResponse<>()
                        .withStatus(HttpStatus.BAD_REQUEST)
                        .withMessage("Bad request: missing or invalid headers"));
    }
}

By adding HttpMediaTypeNotSupportedException, your application will now also handle cases where the client omits the Content-Type header or uses an unsupported media type such as text/plain instead of application/json.


Optional: Add a Custom Filter for Header Validation

If you want finer control and early validation before Spring parses the request, you can add a Servlet filter to inspect headers:

@Component
public class ContentTypeValidationFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String contentType = httpRequest.getHeader("Content-Type");

        if (httpRequest.getMethod().equalsIgnoreCase("POST") && (contentType == null || contentType.isBlank())) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.sendError(HttpStatus.BAD_REQUEST.value(), "Missing Content-Type header");
            return;
        }

        chain.doFilter(request, response);
    }
}

This ensures the API always rejects invalid requests consistently — even before they reach your controller.


Best Practices for Header Validation

  • ✅ Always declare mandatory headers using @RequestHeader with required = true (default).
  • ✅ Use a global @ControllerAdvice to centralize error handling.
  • ✅ Include HttpMediaTypeNotSupportedException in your exception handling to catch Content-Type issues.
  • ✅ Add integration tests to verify missing or malformed header responses.
  • ✅ Document expected headers clearly in your API specification (e.g., with Swagger or OpenAPI).

Conclusion

Handling headers consistently in a Spring Boot REST API ensures predictable and professional behavior.
While authToken or Protocol-Version are caught by MissingRequestHeaderException, Content-Type requires special attention because of how Spring parses the request body.

By extending your @ControllerAdvice with HttpMediaTypeNotSupportedException or introducing a simple filter, you can ensure that every missing Content-Type header results in a clean, meaningful 400 Bad Request response — improving both security and API reliability.

This article is inspired by real-world challenges we tackle in our projects. If you're looking for expert solutions or need a team to bring your idea to life,

Let's talk!

    Please fill your details, and we will contact you back

      Please fill your details, and we will contact you back