{"record":{"id":"fccda7079cccabec","repo":"spring-projects/spring-security","slug":"failed-to-lazily-resolve-the-supplied-jwtdecoder-i","errorCode":null,"errorMessage":"Failed to lazily resolve the supplied JwtDecoder instance","messagePattern":"Failed to lazily resolve the supplied JwtDecoder instance","errorType":"exception","errorClass":"JwtDecoderInitializationException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/SupplierJwtDecoder.java","lineNumber":39,"sourceCode":"import org.springframework.util.function.SingletonSupplier;\n\n/**\n * A {@link JwtDecoder} that lazily initializes another {@link JwtDecoder}.\n *\n * @author Josh Cummings\n * @since 5.6\n */\npublic final class SupplierJwtDecoder implements JwtDecoder {\n\n\tprivate final Supplier<JwtDecoder> delegate;\n\n\tpublic SupplierJwtDecoder(Supplier<JwtDecoder> jwtDecoderSupplier) {\n\t\tthis.delegate = SingletonSupplier.of(() -> {\n\t\t\ttry {\n\t\t\t\treturn jwtDecoderSupplier.get();\n\t\t\t}\n\t\t\tcatch (Exception ex) {\n\t\t\t\tthrow wrapException(ex);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t */\n\t@Override\n\tpublic Jwt decode(String token) throws JwtException {\n\t\treturn this.delegate.get().decode(token);\n\t}\n\n\tprivate JwtDecoderInitializationException wrapException(Exception ex) {\n\t\treturn new JwtDecoderInitializationException(\"Failed to lazily resolve the supplied JwtDecoder instance\", ex);\n\t}\n\n}\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/SupplierJwtDecoder.java#L21-L57","documentation":"SupplierJwtDecoder resolves its JwtDecoder lazily via a Supplier, memoizing the result in a SingletonSupplier. If the supplier throws when first invoked, the exception is wrapped and rethrown as IllegalStateException with message 'Failed to lazily resolve the supplied JwtDecoder instance', preserving the cause. Subsequent decodes retry the supplier since resolution failed.","triggerScenarios":"The supplied JwtDecoder factory fails on first decode call, e.g. a NimbusJwtDecoder built from a JwkSetUri whose JWKS endpoint is unreachable, a misconfigured issuer URI, or a supplier throwing while reading keys.","commonSituations":"Resource server starting before the authorization server's JWKS endpoint is up, wrong jwk-set URI or network/firewall issues, misconfigured OAuth2 issuer, or a supplier that throws NPE due to missing beans.","solutions":["Inspect the cause (getCause()) to find the underlying supplier failure","Verify the jwk-set URI / issuer configuration points at a reachable JWKS endpoint","Ensure the authorization server is running before the resource server decodes tokens","Add retry/backoff: the supplier is re-invoked on the next decode, so a transient outage self-heals"],"exampleFix":"// before\nnew SupplierJwtDecoder(() -> { throw new IllegalArgumentException(\"bad uri\"); })\n// after: validate config before constructing\n@Bean\nJwtDecoder jwtDecoder() {\n    return new SupplierJwtDecoder(() -> {\n        String uri = env.getRequiredProperty(\"spring.security.oauth2.resourceserver.jwt.jwk-set-uri\");\n        return NimbusJwtDecoder.withJwkSetUri(uri).build();\n    });\n}","handlingStrategy":"try-catch","validationCode":"// fail fast at startup instead of lazily\nJwtDecoder d = new SupplierJwtDecoder(supplier);\nd.decode(\"eyJhbGciOi...\"); // warm up and surface config errors at boot","typeGuard":null,"tryCatchPattern":"try {\n    Jwt jwt = decoder.decode(token);\n} catch (IllegalStateException ex) {\n    Throwable cause = ex.getCause(); // real reason: unreachable JWKS, bad issuer, etc.\n    log.error(\"JwtDecoder failed to resolve lazily\", cause);\n    // retry is safe: the supplier is re-invoked on next decode\n}","preventionTips":["Validate jwk-set-uri / issuer configuration at startup with a warm-up decode","Ensure the authorization server's JWKS endpoint is reachable from the resource server","Monitor the cause chain; IllegalStateException here always wraps the real error"],"tags":["jwt","resource-server","lazy-initialization"],"backgroundTag":"invalid-config-value","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}