quarkusio/quarkus · error · NotSupportedException
The content-type header value did not match the value in @Co
Error message
The content-type header value did not match the value in @Consumes
What it means
RESTEasy Reactive throws this NotSupportedException (HTTP 415) when the request's Content-Type header cannot be matched against the @Consumes media types declared on the target resource method. The library parses the header via MediaTypeHelper.valueOf and checks compatibility with the method's consumed types using getFirstMatch; if no match exists, it rejects the request per the JAX-RS spec. This happens in validateConsumes during request routing, before the resource method is invoked.
Source
Thrown at independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/HandlerMediaTypeUtil.java:36
import org.jboss.resteasy.reactive.server.mapping.RuntimeResource;
class HandlerMediaTypeUtil {
private static final String INVALID_ACCEPT_HEADER_MESSAGE = "The accept header value did not match the value in @Produces";
private static final String MALFORMED_ACCEPT_HEADER_MESSAGE = "The accept header value did not correspond to a valid media type";
// according to the spec we need to return HTTP 415 when content-type header doesn't match what is specified in @Consumes
// HttpMethod being null means this is a sub resource locator method. The handler chain of the sub resource has to match the content-type header
static void validateConsumes(RequestMapper.RequestMatch<RuntimeResource> target,
ResteasyReactiveRequestContext requestContext) {
if (target.value.getHttpMethod() != null && !target.value.getConsumes().isEmpty()) {
String contentType = (String) requestContext.getHeader(HttpHeaders.CONTENT_TYPE, true);
if (contentType != null) {
try {
if (MediaTypeHelper.getFirstMatch(
target.value.getConsumes(),
Collections.singletonList(MediaTypeHelper.valueOf(contentType))) == null) {
throw new NotSupportedException("The content-type header value did not match the value in @Consumes");
}
} catch (IllegalArgumentException e) {
throw new NotSupportedException("The content-type header value did not correspond to a valid media type");
}
}
}
}
// according to the spec we need to return HTTP 406 when Accept header doesn't match what is specified in @Produces.
// A fully unparseable Accept header is a client syntax error and returns HTTP 400 instead.
// HttpMethod being null means this is a sub resource locator method. The handler chain of the sub resource has to match the accept header
static void validateProduces(RequestMapper.RequestMatch<RuntimeResource> target,
ResteasyReactiveRequestContext requestContext) {
if (target.value.getHttpMethod() != null && target.value.getProduces() != null) {
// there could potentially be multiple Accept headers and we need to response with 406
// if none match the method's @Produces
List<String> accepts = (List<String>) requestContext.getHeader(HttpHeaders.ACCEPT, false);
if (!accepts.isEmpty()) {View on GitHub (pinned to e1c734241f)
Solutions
- Set the client request's Content-Type header to one of the media types in the endpoint's @Consumes annotation.
- Widen or add media types on the server, e.g. change @Consumes(MediaType.APPLICATION_JSON) to @Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN}).
- Remove the restrictive @Consumes annotation entirely to accept any content type (wildcard).
Example fix
// before
@POST
@Consumes(MediaType.APPLICATION_JSON)
public String create(Form form) { ... }
// after
@POST
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_FORM_URLENCODED})
public String create(Form form) { ... } Defensive patterns
Strategy: validation
Validate before calling
// client-side, before sending
String contentType = "application/json";
if (!contentType.matches("[\w!#$&^_.+-]+/[\w!#$&^_.+-]+.*")) {
throw new IllegalArgumentException("Invalid Content-Type: " + contentType);
}
// ensure it matches the endpoint's declared @Consumes Try / catch
try {
Response r = client.post(entity);
} catch (NotSupportedException | ProcessingException e) {
// check response status 415 and log the Content-Type sent
} Prevention
- Always set Content-Type explicitly on requests with bodies.
- Keep @Consumes values in sync with what clients actually send.
- Cover each media-type variant with an integration test.
When it happens
Trigger: A request is routed to a resource method with a non-empty @Consumes declaration, the Content-Type header is present, MediaTypeHelper.getFirstMatch(target.value.getConsumes(), [parsed content-type]) returns null — e.g. sending Content-Type: text/plain to a method annotated @Consumes(MediaType.APPLICATION_JSON).
Common situations: Clients posting form data (application/x-www-form-urlencoded) to JSON-only endpoints; frontends sending application/json but the endpoint declared text/plain or vice versa; copying endpoint code and forgetting to update @Consumes; API clients defaulting to text/xml or missing charset variants.
Related errors
- The content-type header value did not correspond to a valid
- The content-type header value did not match the value in @Co
- The content-type header value did not correspond to a valid
- Extra steps left over
- Unsupported value type: %s
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/56c57a6683c58ee0.
Report an issue: GitHub.