{"record":{"id":"2cd95c6b2a4f3441","repo":"spring-projects/spring-security","slug":"failed-to-encode-the-jwt-due-to-signing-error-una","errorCode":null,"errorMessage":"Failed to encode the JWT due to signing error: Unable to convert 'jwk' JOSE header","messagePattern":"Failed to encode the JWT due to signing error: Unable to convert 'jwk' JOSE header","errorType":"exception","errorClass":"JwtEncodingException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtEncoder.java","lineNumber":303,"sourceCode":"\t\t}\n\t}\n\n\tprivate static JWSHeader convert(JwsHeader headers) {\n\t\tJwsAlgorithm algorithm = headers.getAlgorithm();\n\t\tAssert.notNull(algorithm, \"JWS header algorithm must not be null\");\n\t\tJWSHeader.Builder builder = new JWSHeader.Builder(JWSAlgorithm.parse(algorithm.getName()));\n\n\t\tif (headers.getJwkSetUrl() != null) {\n\t\t\tbuilder.jwkURL(convertAsURI(JoseHeaderNames.JKU, headers.getJwkSetUrl()));\n\t\t}\n\n\t\tMap<String, Object> jwk = headers.getJwk();\n\t\tif (!CollectionUtils.isEmpty(jwk)) {\n\t\t\ttry {\n\t\t\t\tbuilder.jwk(JWK.parse(jwk));\n\t\t\t}\n\t\t\tcatch (Exception ex) {\n\t\t\t\tthrow new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,\n\t\t\t\t\t\t\"Unable to convert '\" + JoseHeaderNames.JWK + \"' JOSE header\"), ex);\n\t\t\t}\n\t\t}\n\n\t\tString keyId = headers.getKeyId();\n\t\tif (StringUtils.hasText(keyId)) {\n\t\t\tbuilder.keyID(keyId);\n\t\t}\n\n\t\tif (headers.getX509Url() != null) {\n\t\t\tbuilder.x509CertURL(convertAsURI(JoseHeaderNames.X5U, headers.getX509Url()));\n\t\t}\n\n\t\tList<String> x509CertificateChain = headers.getX509CertificateChain();\n\t\tif (!CollectionUtils.isEmpty(x509CertificateChain)) {\n\t\t\tList<Base64> x5cList = new ArrayList<>();\n\t\t\tx509CertificateChain.forEach((x5c) -> x5cList.add(new Base64(x5c)));\n\t\t\tif (!x5cList.isEmpty()) {","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtEncoder.java#L285-L321","documentation":"NimbusJwtEncoder's header converter tries to parse the user-supplied 'jwk' JOSE header map into a nimbus-jose-jwt JWK via JWK.parse() and wraps any failure in a JwtEncodingException. It means the Map<String,Object> set as the jwk header (e.g. to embed a public key via 'jwk' or trigger key thumbprint embedding) is not a valid JWK JSON structure. The library rejects it early so no malformed JWS is produced.","triggerScenarios":"Calling JwsHeader.with(...).jwk(Map<String,Object>) with a map that lacks required JWK fields ('kty'), contains values of wrong types (e.g. numbers where strings are required), or nested structures JWK.parse() cannot read; passing a full private-key map with unsupported extra members.","commonSituations":"Copying a PEM or X.509 structure into the jwk header instead of a proper JWK; building the map from a properties file where 'kty' was dropped; using snake_case or wrong parameter names (e.g. 'key_type' instead of 'kty'); serializing a JWK to JSON but double-decoding it so values arrive as nested JSON strings.","solutions":["Ensure the map contains at least the mandatory 'kty' member ('RSA', 'EC', 'oct') with string values, per RFC 7517.","Instead of a hand-built map, serialize a real nimbus JWK: jwk.toJSONObject() and pass that map, guaranteeing structural validity.","Inspect the cause via getCause() — JWK.parse reports the missing/invalid member.","If you only need kid/thumbprint, use .keyId(...) or .jwk(URI/ thumbprint) options rather than embedding a raw jwk map."],"exampleFix":"// before\nMap<String, Object> jwk = Map.of(\"key_type\", \"RSA\", \"n\", n, \"e\", e);\n// after\nMap<String, Object> jwk = rsaKey.toJSONObject(); // has \"kty\":\"RSA\", \"n\", \"e\"","handlingStrategy":"validation","validationCode":"// validate a jwk header map before passing to JwsHeader.with(...).jwk(map)\nif (!(jwk.get(\"kty\") instanceof String kty) || kty.isBlank()) {\n    throw new IllegalArgumentException(\"jwk header map missing required 'kty'\");\n}\nJWK.parse(jwk); // dry-run parse; throws if structure invalid","typeGuard":null,"tryCatchPattern":"try {\n    token = jwtEncoder.encode(params);\n} catch (JwtEncodingException ex) {\n    if (ex.getMessage().contains(\"'jwk' JOSE header\")) {\n        throw new IllegalArgumentException(\"Embedded jwk header is not a valid JWK\", ex);\n    }\n    throw ex;\n}","preventionTips":["Build jwk header maps from a nimbus JWK instance's toJSONObject(), never by hand.","Always include 'kty' and use RFC 7517 member names exactly.","Add a startup test that round-trips your header map through JWK.parse().","Prefer keyId/keyURL header options over embedding raw JWK JSON when possible."],"tags":["jwt","jose-header","jwk","spring-security","header-validation"],"backgroundTag":"schema-validation-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"}