{"record":{"id":"d974943895895ca0","repo":"spring-projects/spring-security","slug":"failed-to-encode-the-jwt-due-to-signing-error-fai-d97494","errorCode":null,"errorMessage":"Failed to encode the JWT due to signing error: Failed to select a JWK signing key","messagePattern":"Failed to encode the JWT due to signing error: Failed to select a JWK signing key","errorType":"exception","errorClass":"JwtEncodingException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtEncoder.java","lineNumber":201,"sourceCode":"\t\theaders = addKeyIdentifierHeadersIfNecessary(headers, jwk);\n\n\t\tString jws = serialize(headers, claims, jwk);\n\n\t\treturn new Jwt(jws, claims.getIssuedAt(), claims.getExpiresAt(), headers.getHeaders(), claims.getClaims());\n\t}\n\n\tprivate JWK selectJwk(JwsHeader headers) {\n\t\tList<JWK> jwks;\n\t\ttry {\n\t\t\tJWKSelector jwkSelector = new JWKSelector(createJwkMatcher(headers));\n\t\t\tjwks = this.jwkSource.get(jwkSelector, null);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,\n\t\t\t\t\t\"Failed to select a JWK signing key -> \" + ex.getMessage()), ex);\n\t\t}\n\t\tif (jwks.isEmpty()) {\n\t\t\tthrow new JwtEncodingException(\n\t\t\t\t\tString.format(ENCODING_ERROR_MESSAGE_TEMPLATE, \"Failed to select a JWK signing key\"));\n\t\t}\n\t\tif (jwks.size() == 1) {\n\t\t\treturn jwks.get(0);\n\t\t}\n\t\treturn this.jwkSelector.convert(jwks);\n\t}\n\n\tprivate String serialize(JwsHeader headers, JwtClaimsSet claims, JWK jwk) {\n\t\tJWSHeader jwsHeader = convert(headers);\n\t\tJWTClaimsSet jwtClaimsSet = convert(claims);\n\n\t\tJWSSigner jwsSigner = this.jwsSigners.computeIfAbsent(jwk, NimbusJwtEncoder::createSigner);\n\n\t\tSignedJWT signedJwt = new SignedJWT(jwsHeader, jwtClaimsSet);\n\t\ttry {\n\t\t\tsignedJwt.sign(jwsSigner);\n\t\t}","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtEncoder.java#L183-L219","documentation":"NimbusJwtEncoder.selectJwk throws this when the JWKSource query succeeds but returns an empty key list — no JWK in the source matches the JWT's headers (algorithm, key use, key ID, etc.). Without a signing key the JWT cannot be encoded, so a JwtEncodingException is raised with the static message \"Failed to select a JWK signing key\".","triggerScenarios":"encode(JwtEncoderParameters) whose JWS header algorithm (e.g. RS256, ES256) or kid does not match any key in the configured JWKSet/JWKSource — e.g. source holds only an EC key while the parameters request RSA256, no \"use\":\"sig\" set, or the kid in headers doesn't exist in the key set.","commonSituations":"Mismatch between the JWKSet loaded into NimbusJwtEncoder and the JWSAlgorithm passed in JwsHeader.withAlgorithm(...); keys created without \"use\":\"sig\"; kid typos after key rotation; using an octet (symmetric) key where an asymmetric one is required or vice versa; empty/default-constructed JWKSet.","solutions":["Ensure the JWKSource contains at least one signing key supporting the requested algorithm: generate with e.g. com.nimbusds.jose.jwk.KeyUse.SIGNATURE and the matching KeyType.","Match the algorithm in JwtEncoderParameters' JwsHeader to an available key's algorithm, or add the required key to the JWKSet.","Verify each JWK has use = KeyUse.SIGNATURE (or no use restriction) so the JWKSelector matcher can match it.","If headers carry a kid, confirm it exactly matches a getKeyID() of a key in the source (or omit kid).","Print/log jwkSource.get(new JWKSelector(new JWKMatcher.Builder().build()), null) to see what keys are actually available and adjust the request."],"exampleFix":"// before\nRSAKey rsaKey = new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(\"k1\").build(); // no key use\nJWKSet jwkSet = new JWKSet(rsaKey);\n// after\nRSAKey rsaKey = new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(\"k1\")\n\t.keyUse(KeyUse.SIGNATURE).algorithm(JWSAlgorithm.RS256).build();\nJWKSet jwkSet = new JWKSet(rsaKey);\n// and request the same algorithm:\nJwsHeader.with(JWSAlgorithm.RS256).build();","handlingStrategy":"validation","validationCode":"// Before encoding, verify a key matching the requested algorithm exists in the source\nJwsHeader header = params.getJwsHeaders();\nString alg = header.getAlgorithm().getName();\nList<JWK> matches = jwkSource.get(\n\tnew JWKSelector(new JWKMatcher.Builder().algorithm(alg).build()), null);\nif (matches.isEmpty()) {\n\tthrow new IllegalStateException(\n\t\t\"No JWK for algorithm \" + alg + \"; JWKSet contains: \"\n\t\t\t+ jwkSource.get(new JWKSelector(new JWKMatcher.Builder().build()), null));\n}","typeGuard":null,"tryCatchPattern":"try {\n\tJwt jwt = encoder.encode(params);\n} catch (org.springframework.security.oauth2.jwt.JwtEncodingException ex) {\n\tif (ex.getMessage().endsWith(\"Failed to select a JWK signing key\")) {\n\t\tlog.error(\"No JWK matched headers alg={}; check JWKSet keys, key use, and kid\",\n\t\t\tparams.getJwsHeaders().getAlgorithm());\n\t}\n\tthrow ex;\n}","preventionTips":["Generate JWKs with KeyUse.SIGNATURE and the algorithm you intend to request","Keep the encoder's algorithm in JwsHeader.with(...) in sync with the keys in the JWKSource","If using kid in headers, verify it exists in the JWKSet after rotation","Assert at startup that JWKSet contains at least one signing key per supported algorithm"],"tags":["jwt","jwk","signing","algorithm-mismatch","spring-security"],"backgroundTag":"jwt-signing-key-selection-failed","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"}