quarkusio/quarkus · error · WebApplicationException

HTTP 406 Not Acceptable (no acceptable MessageBodyWriter for

Error message

HTTP 406 Not Acceptable (no acceptable MessageBodyWriter for the requested media types)

What it means

When a resource method's writers are constrained to specific media types and ServerSerialisers.findWriterNoMediaType cannot select a writer matching the request's Accept header, it throws a WebApplicationException carrying an HTTP 406 Not Acceptable response that lists the media types the resource can produce.

Source

Thrown at independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/ServerSerialisers.java:387

                continue;
            }
            constrainedResultsForClass.add(writer);
        }
        MediaType selected = null;
        for (ResourceWriter writer : constrainedResultsForClass) {
            selected = writer.serverMediaType()
                    .negotiateProduces(requestContext.serverRequest().getRequestHeader(HttpHeaders.ACCEPT)).getKey();
            if (selected != null) {
                break;
            }
        }
        if (selected == null) {
            Set<MediaType> acceptable = new HashSet<>();
            for (ResourceWriter i : constrainedResultsForClass) {
                acceptable.addAll(i.mediaTypes());
            }

            throw new WebApplicationException(Response
                    .notAcceptable(Variant
                            .mediaTypes(
                                    acceptable.toArray(new MediaType[0]))
                            .build())
                    .build());
        }
        if (selected.isWildcardType() || (selected.getType().equals("application") && selected.isWildcardSubtype())) {
            selected = MediaType.APPLICATION_OCTET_STREAM_TYPE;
        }
        List<MessageBodyWriter<?>> finalResult = new ArrayList<>(constrainedResultsForClass.size());
        for (ResourceWriter i : constrainedResultsForClass) {
            // this part seems to be needed in order to pass com.sun.ts.tests.jaxrs.ee.resource.java2entity.JAXRSClient
            if (i.mediaTypes().isEmpty()) {
                finalResult.add(i.instance());
            } else {
                for (MediaType mt : i.mediaTypes()) {
                    if (mt.isCompatible(selected)) {
                        finalResult.add(i.instance());

View on GitHub (pinned to e1c734241f)

Solutions

  1. Fix the client's Accept header to include a media type the endpoint produces (e.g. application/json).
  2. Broaden the endpoint's @Produces annotation if it should serve additional media types, and register the corresponding MessageBodyWriter.
  3. If content negotiation is meant to be flexible, use @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) with writers for each.
  4. Verify any reverse proxy is not stripping or rewriting the Accept header incorrectly.

Example fix

// before
@Produces(MediaType.APPLICATION_JSON)
public User get() { ... }
// client sends: Accept: application/xml
// after
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public User get() { ... }
Defensive patterns

Strategy: try-catch

Validate before calling

// client-side: check Accept compatibility before calling
String produces = "application/json"; // from API docs/OpenAPI
String accept = myAcceptHeader;
if (!accept.contains(produces.split("/")[0])) {
    log.warn("Accept header " + accept + " may cause HTTP 406 on this endpoint");
}

Try / catch

try {
    response = client.target(url).request(accept).get();
} catch (NotAcceptableException e) { // 406
    log.warn("Endpoint cannot produce any requested media type; retrying with application/json");
    response = client.target(url).request(MediaType.APPLICATION_JSON).get();
}

Prevention

When it happens

Trigger: A client sends an Accept header that intersects none of the @Produces media types of the matched resource method/class — e.g. requesting Accept: application/xml while the endpoint only produces application/json.

Common situations: API clients hard-coding Accept: application/xml against JSON-only endpoints; proxies/gateways adding or rewriting Accept headers; new content-type requirements added to clients after server-side @Produces was narrowed.

Understand the failure class

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/d4cecfdd6a14dc34. Report an issue: GitHub.