keycloak/keycloak · error · RuntimeException

Error executing http method [{builder.getMethod()}]. Respons

Error message

Error executing http method [{builder.getMethod()}]. Response : {String.valueOf(bytes)}

What it means

This is the generic catch-all RuntimeException thrown by the Keycloak authz client's HttpMethod.execute() when an HTTP call fails for any reason OTHER than a non-2xx HTTP status (those are re-thrown as HttpResponseException at HttpMethod.java:104). It wraps the original Exception and includes the HTTP method (GET/POST/etc.) and the raw response bytes that were read so far. The wrapped cause is the real signal: an IOException means a transport/ connectivity failure, while a non-IO exception from responseProcessor.process(bytes) means the body could not be parsed even though the status was 2xx.

Source

Thrown at authz/client/src/main/java/org/keycloak/authorization/client/util/HttpMethod.java:115

            int statusCode = statusLine.getStatusCode();

            if(logger.isLoggable(Level.FINE)) {
                logger.fine( "Response from server: " + statusCode + " / " + statusLine.getReasonPhrase() +  " / Body : " + new String(bytes != null? bytes: new byte[0]));
            }

            if (statusCode < 200 || statusCode >= 300) {
                throw new HttpResponseException("Unexpected response from server: " + statusCode + " / " + statusLine.getReasonPhrase(), statusCode, statusLine.getReasonPhrase(), bytes);
            }

            if (bytes == null) {
                return null;
            }

            return responseProcessor.process(bytes);
        } catch (HttpResponseException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("Error executing http method [" + builder.getMethod() + "]. Response : " + String.valueOf(bytes), e);
        }
    }

    protected void preExecute(RequestBuilder builder) {
        for (Map.Entry<String, List<String>> param : params.entrySet()) {
            for (String value : param.getValue()) {
                builder.addParameter(param.getKey(), value);
            }
        }
    }

    public HttpMethod<R> authorizationBearer(String bearer) {
        this.builder.addHeader("Authorization", "Bearer " + bearer);
        return this;
    }

    public HttpMethodResponse<R> response() {
        this.response = new HttpMethodResponse(this);

View on GitHub (pinned to 66c7e15a37)

Solutions

  1. Inspect the wrapped exception's cause (e.getCause()) and its type: an IOException or UnknownHostException points to a network/connectivity/URL problem, while a JsonParseException/MismatchedInputException points to an unexpected response body.
  2. Enable FINE logging on org.keycloak.authorization.client.util.HttpMethod to see the actual status line and body logged at line 100, which shows exactly what the server returned.
  3. Verify the Configuration.getAuthServerUrl() is reachable and returns Keycloak JSON (curl the /realms/{realm} endpoint directly).
  4. If the cause is JSON parsing on a 2xx, check for a proxy/gateway intercepting the response or a Keycloak client/server version mismatch.
  5. Check the client's truststore and TLS configuration if the cause is a handshake/SSLException.

Example fix

// before: opaque error with no context
try {
    authzClient.protection().resource().findAll();
} catch (RuntimeException e) {
    log.error("failed", e); // 'Error executing http method [GET]. Response : ...'
}

// after: unwrap the real cause and distinguish transport vs parse failures
try {
    authzClient.protection().resource().findAll();
} catch (HttpResponseException hre) {
    // genuine non-2xx from server
    log.error("server returned {} {}", hre.getStatusCode(), hre.getReasonPhrase());
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof java.io.IOException) {
        log.error("transport failure talking to Keycloak", cause);
    } else {
        log.error("unexpected response body, could not parse", cause);
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate reachability before relying on the authz client
java.net.URL u = new java.net.URL(config.getAuthServerUrl() + "/realms/" + config.getRealm());
try (java.net.HttpURLConnection c = (java.net.HttpURLConnection) u.openConnection()) {
    c.setConnectTimeout(2000); c.setRequestMethod("GET");
    int code = c.getResponseCode();
    if (code != 200) throw new IllegalStateException("Keycloak realm endpoint returned " + code);
}

Try / catch

import org.keycloak.authorization.client.util.HttpResponseException;
try {
    authzClient.protection().resource().findAll();
} catch (HttpResponseException hre) {
    // server returned non-2xx: genuine HTTP error
    handleServerError(hre.getStatusCode(), hre.getReasonPhrase(), hre.getResponse());
} catch (RuntimeException e) {
    // this catch sees the 'Error executing http method' wrapper
    Throwable cause = e.getCause();
    if (cause instanceof java.io.IOException) {
        handleTransportFailure(cause); // connectivity/TLS/timeout
    } else {
        handleParseFailure(cause); // 2xx body not parseable
    }
}

Prevention

When it happens

Trigger: Any authz-client call that hits the token, resource, permission, or entitlement endpoints (e.g. AuthzClient.protection().resource().findAll(), a UMA authorization request, or token obtain/refresh) can surface this. It fires when (a) the server is unreachable, TLS handshake fails, or the socket times out during httpClient.execute(builder.build()), or (b) the server returned a 2xx with a body that the configured responseProcessor (JSON deserializer) cannot parse. Note: a genuine 4xx/5xx from the server is NOT this error — it becomes HttpResponseException and is re-thrown at line 113, never reaching this catch block.

Common situations: Wrong/authUrl base in Configuration; Keycloak server down or behind a proxy that returns an HTML error page (which then fails JSON parsing on a 2xx); expired/invalid client secret causing a redirect; SSL/cert issues in JDK truststore; clock skew; load balancer returning a 200 health-check page instead of the expected JSON; version mismatch where the server returns a newer JSON shape than the client can deserialize.

Related errors


AI-assisted analysis of keycloak/keycloak@66c7e15a37 (2026-08-14). Data as JSON: /api/errors/74c7a502c9f29709. Report an issue: GitHub.