quarkusio/quarkus · error · IllegalStateException

A REST Client Response object was returned from a server end

Error message

A REST Client Response object was returned from a server endpoint. This is not supported because it carries connection-specific headers that are not suitable for forwarding. Please create a new Response using Response.fromResponse() or by extracting the status, entity and headers you need.

What it means

The server endpoint returned a JAX-RS Response produced by a REST Client call (resteasy-reactive's ResponseImpl flagged as a client response). Client responses hold connection-specific state (underlying HTTP connection headers, closed streams) that cannot be forwarded as a server response, so the server rejects it with IllegalStateException instead of producing a corrupt response.

Source

Thrown at independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/ResponseHandler.java:51

    private static final Set<String> IGNORED_HEADERS = Collections.singleton(ServerSerialisers.TRANSFER_ENCODING.toLowerCase(
            Locale.ROOT));

    private final List<ResponseBuilderCustomizer> responseBuilderCustomizers;

    public ResponseHandler(List<ResponseBuilderCustomizer> responseBuilderCustomizers) {
        this.responseBuilderCustomizers = responseBuilderCustomizers;
    }

    private ResponseHandler() {
        this.responseBuilderCustomizers = Collections.emptyList();
    }

    @Override
    public void handle(ResteasyReactiveRequestContext requestContext) throws Exception {
        Object result = requestContext.getResult();
        if (result instanceof Response existing) {
            if (existing instanceof ResponseImpl responseImpl && responseImpl.isClientResponse()) {
                throw new IllegalStateException(
                        "A REST Client Response object was returned from a server endpoint. "
                                + "This is not supported because it carries connection-specific headers "
                                + "that are not suitable for forwarding. "
                                + "Please create a new Response using Response.fromResponse() or "
                                + "by extracting the status, entity and headers you need.");
            }
            boolean mediaTypeAlreadyExists = false;
            //we already have a response
            //set it explicitly
            ResponseBuilderImpl responseBuilder;
            if (existing.getEntity() instanceof GenericEntity<?> genericEntity) {
                requestContext.setGenericReturnType(genericEntity.getType());
                responseBuilder = fromResponse(existing);
                responseBuilder.entity(genericEntity.getEntity());
            } else {
                // TCK says to use the entity type as generic type if we return a response
                if (existing.hasEntity() && (existing.getEntity() != null))
                    requestContext.setGenericReturnType(existing.getEntity().getClass());

View on GitHub (pinned to e1c734241f)

Solutions

  1. Create a new server Response with Response.fromResponse(existing)
  2. Extract status, entity and headers and rebuild via Response.ok(...).status(...).header(...)
  3. Read the entity first (existing.readEntity(...)) and return that object directly
  4. If proxying is intended, copy only safe headers explicitly

Example fix

// before
@GET
public Response proxy() {
    return client.get(); // client Response
}
// after
@GET
public Response proxy() {
    Response existing = client.get();
    return Response.fromResponse(existing);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (result instanceof ResponseImpl r && r.isClientResponse()) result = Response.fromResponse(r);

Type guard

static boolean isServerResponse(Response r) {
    return !(r instanceof org.jboss.resteasy.reactive.server.jaxrs.ResponseImpl impl && impl.isClientResponse());
}

Try / catch

try { return proxy(); } catch (IllegalStateException e) { if (e.getMessage().contains("REST Client Response")) { return Response.fromResponse(clientResp); } throw e; }

Prevention

When it happens

Trigger: A resource method returns the Response object obtained directly from a REST Client interface call (or RestResponse/Uni<Response> unwrapped to a client ResponseImpl) instead of building a new server-side Response.

Common situations: Proxying another service's response verbatim; refactoring a client call into a resource method return; forgetting that quarkus-rest-client Response types are distinct from server Response implementations.

Related errors


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