alibaba/nacos · error · IOException

Failed to fetch JWKS, status:

Error message

Failed to fetch JWKS, status: 

What it means

Thrown when the JWKS HTTP GET returned a non-200 status. The status code is appended. Nacos built the JWKS URL from discovery but the endpoint rejected or failed the request.

Source

Thrown at plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/token/JwksProvider.java:114

     */
    public JWKSet refreshJwkSet() throws IOException {
        jwksCache.invalidateAll();
        return getJwkSet();
    }
    
    private JWKSet fetchJwkSet() throws IOException {
        String jwksUri = metadataProvider.getMetadata().getJwksUri();
        if (StringUtils.isBlank(jwksUri)) {
            throw new IOException("JWKS URI is not configured or discovered");
        }
        LOGGER.info("Fetching JWKS from: {}", jwksUri);
        HttpRequest request = HttpRequest.newBuilder().uri(URI.create(jwksUri))
            .header("Accept", "application/json").GET().build();
        try {
            HttpResponse<String> response =
                httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() != OidcProtocolConstants.HTTP_STATUS_OK) {
                throw new IOException("Failed to fetch JWKS, status: " + response.statusCode());
            }
            JWKSet result = JWKSet.parse(response.body());
            LOGGER.info("Successfully fetched JWKS with {} keys", result.getKeys().size());
            return result;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("JWKS fetch interrupted", e);
        } catch (ParseException e) {
            throw new IOException("Failed to parse JWKS", e);
        }
    }
    
    /**
     * Clear the cached JWK set.
     */
    public void clearCache() {
        jwksCache.invalidateAll();
    }

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. curl the jwks_uri from the discovery doc and read the appended status code.
  2. For 404: the jwks_uri in discovery is incorrect — fix the IdP discovery configuration.
  3. For 401/403: ensure the JWKS endpoint is public per OIDC spec.
  4. For 5xx: check IdP health and retry; the cache TTL (jwks-cache-ttl-seconds) means failures retry on next validation after expiry.
  5. Verify outbound HTTPS connectivity from the Nacos host to the JWKS URL.
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: probe the JWKS endpoint status before relying on key fetch
// (curl the jwks_uri and assert HTTP 200)

Try / catch

try {
    jwksProvider.getJwkSet();
} catch (IOException e) {
    if (e.getMessage().contains("status:")) {
        // transient IdP issue — the Caffeine cache will retry on next miss after TTL
        log.warn("JWKS fetch non-200; will retry: {}", e.getMessage());
        jwksProvider.refreshJwkSet();
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: JwksProvider.getJwkSet() fetches <jwks_uri> and receives 404, 401/403, 500, etc. Occurs during JWT validation when the cache is cold or expired.

Common situations: jwks_uri from discovery is wrong/stale; JWKS endpoint requires authentication (non-standard); IdP down; key-rotation endpoint temporarily unavailable; corporate proxy blocking the JWKS host.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/4bae904febe6715b. Report an issue: GitHub.