apache/pulsar · error · IOException

Cannot obtain authorization metadata from ${metadataUrl}

Error message

Cannot obtain authorization metadata from ${metadataUrl}

What it means

DefaultMetadataResolver.resolve fetches the OIDC authorization-server metadata document from metadataUrl and deserializes it. If fetching fails (IOException, thread interrupted, or the async execution fails), this IOException is thrown wrapping the cause. The library could not obtain the discovery document needed to locate the token endpoint.

Source

Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/DefaultMetadataResolver.java:117

     * Resolves the authorization metadata.
     *
     * @return metadata
     * @throws IOException if the metadata could not be resolved.
     */
    public Metadata resolve() throws IOException {

        try {
            HttpRequest request = HttpRequest.builder(HttpRequest.Method.GET, URI.create(metadataUrl.toString()))
                    .header("Accept", "application/json")
                    .build();
            HttpResponse response = httpClient.execute(request).get();
            return this.objectReader.readValue(response.body());

        } catch (IOException | InterruptedException | ExecutionException e) {
            if (e instanceof InterruptedException) {
                Thread.currentThread().interrupt();
            }
            throw new IOException("Cannot obtain authorization metadata from " + metadataUrl, e);
        }
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Verify metadataUrl is reachable: curl <issuer>/.well-known/openid-configuration and confirm valid JSON comes back.
  2. Fix issuerUrl so it points to the actual IdP issuer (no typos, correct tenant path).
  3. Check network path: proxies, firewalls, DNS, and trust store for the IdP's TLS certificate.
  4. Inspect the wrapped cause (getCause()) for the specific transport failure.

Example fix

// before
String issuer = "https://auth.example.com/realms/typo-realm"; // metadata 404s
// after
String issuer = "https://auth.example.com/realms/my-realm"; // valid discovery doc
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check discovery reachability before wiring the client
HttpRequest req = HttpRequest.newBuilder(URI.create(issuerUrl + "/.well-known/openid-configuration")).GET().build();
HttpResponse<String> resp = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
if (resp.statusCode() != 200 || !resp.body().trim().startsWith("{")) {
    throw new IOException("Discovery metadata not reachable/invalid at " + req.uri());
}

Try / catch

try {
    client = AuthenticationFactoryOAuth2.clientCredentials(issuerUrl, credFile, audience);
} catch (IOException e) {
    if (e.getMessage().startsWith("Cannot obtain authorization metadata")) {
        // wrapped cause has the transport failure: DNS, TLS, interrupt, etc.
        throw new RuntimeException("Cannot reach OIDC discovery at issuer; cause: " + e.getCause(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: resolve() issues an HTTP GET to the issuer's well-known metadata URL and: DNS/connection fails, TLS handshake fails, the IdP returns a non-200 body that can't be read, the response is empty/invalid, or the waiting thread is interrupted.

Common situations: Wrong issuerUrl so the metadata 404s or returns HTML; IdP unreachable from the client network; proxy/firewall blocking HTTPS; expired IdP TLS certificate rejected by the client trust store; IdP outage.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/afba03775cd8989f. Report an issue: GitHub.