{"record":{"id":"eb555dc0e3a6f987","repo":"spring-projects/spring-security","slug":"failed-to-encode-the-jwt-due-to-signing-error-una-eb555d","errorCode":null,"errorMessage":"Failed to encode the JWT due to signing error: Unable to convert '+ header +' JOSE header to a URI","messagePattern":"Failed to encode the JWT due to signing error: Unable to convert '\\+ header \\+' JOSE header to a URI","errorType":"exception","errorClass":"JwtEncodingException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtEncoder.java","lineNumber":421,"sourceCode":"\t\tMap<String, Object> customClaims = new HashMap<>();\n\t\tclaims.getClaims().forEach((name, value) -> {\n\t\t\tif (!JWTClaimsSet.getRegisteredNames().contains(name)) {\n\t\t\t\tcustomClaims.put(name, value);\n\t\t\t}\n\t\t});\n\t\tif (!customClaims.isEmpty()) {\n\t\t\tcustomClaims.forEach(builder::claim);\n\t\t}\n\n\t\treturn builder.build();\n\t}\n\n\tprivate static URI convertAsURI(String header, URL url) {\n\t\ttry {\n\t\t\treturn url.toURI();\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\"Unable to convert '\" + header + \"' JOSE header to a URI\"), ex);\n\t\t}\n\t}\n\n\t/**\n\t * Creates a builder for constructing a {@link NimbusJwtEncoder} using the provided.\n\t * @param publicKey the {@link RSAPublicKey} and @Param privateKey the\n\t * {@link RSAPrivateKey} to use for signing JWTs\n\t * @return a {@link RsaKeyPairJwtEncoderBuilder}\n\t * @since 7.0\n\t */\n\tpublic static RsaKeyPairJwtEncoderBuilder withKeyPair(RSAPublicKey publicKey, RSAPrivateKey privateKey) {\n\t\treturn new RsaKeyPairJwtEncoderBuilder(publicKey, privateKey);\n\t}\n\n\t/**\n\t * Creates a builder for constructing a {@link NimbusJwtEncoder} using the provided.\n\t * @param publicKey the {@link ECPublicKey} and @param privateKey the","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtEncoder.java#L403-L439","documentation":"NimbusJwtEncoder.convertAsURI(String header, URL) converts URL-valued JOSE headers (jku, x5u) to java.net.URI and wraps any conversion failure in a JwtEncodingException. java.net.URL.toURI() throws URISyntaxException when the URL is not a well-formed, RFC 2396-compliant URI (e.g. contains spaces or illegal characters). The library rejects the header rather than emitting a token with an invalid URI header.","triggerScenarios":"Calling JwsHeader.with(...).jwk(url) / x5u(url) (or .header(name, urlValue) for URL headers) where the URL was built from unvalidated user input or config containing spaces, unencoded reserved characters, or a malformed string parsed leniently by URL but rejected by URI.","commonSituations":"jku values assembled by string concatenation without URL-encoding a tenant or filename segment; config entries like 'https://issuer.example.com/keys dir/jwks.json' containing a space; trailing characters copied from docs; environment-specific placeholders left unsubstituted ('${jwks-url}').","solutions":["Print/validate the URL before passing it: new URI(url.toString()) in a test reproduces the exact URISyntaxException and offending character.","URL-encode path segments before constructing the URL (URLEncoder.encode or UriComponentsBuilder).","Fix the source value in configuration/environment — spaces and illegal characters must be removed or percent-encoded.","Verify placeholder substitution so the header never receives raw '${...}' strings."],"exampleFix":"// before\nURL jku = new URL(baseUrl + \"/keys dir/jwks.json\");\n// after\nURL jku = UriComponentsBuilder.fromHttpUrl(baseUrl)\n    .pathSegment(\"keys\", \"jwks.json\")\n    .build().toUri().toURL();","handlingStrategy":"validation","validationCode":"// validate before setting a URL JOSE header\ntry {\n    new URI(jkuUrl.toString());\n} catch (URISyntaxException ex) {\n    throw new IllegalArgumentException(\"jku header value is not a valid URI\", ex);\n}","typeGuard":null,"tryCatchPattern":"try {\n    token = jwtEncoder.encode(params);\n} catch (JwtEncodingException ex) {\n    if (ex.getMessage().endsWith(\"JOSE header to a URI\")) {\n        throw new IllegalArgumentException(\"Fix the URL-valued JOSE header (jku/x5u): \" + ex.getCause().getMessage(), ex);\n    }\n    throw ex;\n}","preventionTips":["Construct URLs with UriComponentsBuilder/URI rather than string concatenation.","Percent-encode all dynamic path/query segments.","Externalize URL-valued header values to validated config and validate at load time.","Check for unsubstituted placeholders and spaces in environment-derived values."],"tags":["jwt","jose-header","uri","spring-security","url-validation"],"backgroundTag":"invalid-url-format","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"}