spring-projects/spring-security · error · JwtEncodingException

Failed to encode the JWT due to signing error: Unable to…

Error message

Failed to encode the JWT due to signing error: Unable to convert '+ header +' JOSE header to a URI

What it means

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.

Solutions

  1. Print/validate the URL before passing it: new URI(url.toString()) in a test reproduces the exact URISyntaxException and offending character.
  2. URL-encode path segments before constructing the URL (URLEncoder.encode or UriComponentsBuilder).
  3. Fix the source value in configuration/environment — spaces and illegal characters must be removed or percent-encoded.
  4. Verify placeholder substitution so the header never receives raw '${...}' strings.

Example fix

// before
URL jku = new URL(baseUrl + "/keys dir/jwks.json");
// after
URL jku = UriComponentsBuilder.fromHttpUrl(baseUrl)
    .pathSegment("keys", "jwks.json")
    .build().toUri().toURL();
Defensive patterns

Strategy: validation

Validate before calling

// validate before setting a URL JOSE header
try {
    new URI(jkuUrl.toString());
} catch (URISyntaxException ex) {
    throw new IllegalArgumentException("jku header value is not a valid URI", ex);
}

Try / catch

try {
    token = jwtEncoder.encode(params);
} catch (JwtEncodingException ex) {
    if (ex.getMessage().endsWith("JOSE header to a URI")) {
        throw new IllegalArgumentException("Fix the URL-valued JOSE header (jku/x5u): " + ex.getCause().getMessage(), ex);
    }
    throw ex;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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}').

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/eb555dc0e3a6f987. Report an issue: GitHub.

Appendix: source

Thrown at oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtEncoder.java:421

		Map<String, Object> customClaims = new HashMap<>();
		claims.getClaims().forEach((name, value) -> {
			if (!JWTClaimsSet.getRegisteredNames().contains(name)) {
				customClaims.put(name, value);
			}
		});
		if (!customClaims.isEmpty()) {
			customClaims.forEach(builder::claim);
		}

		return builder.build();
	}

	private static URI convertAsURI(String header, URL url) {
		try {
			return url.toURI();
		}
		catch (Exception ex) {
			throw new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,
					"Unable to convert '" + header + "' JOSE header to a URI"), ex);
		}
	}

	/**
	 * Creates a builder for constructing a {@link NimbusJwtEncoder} using the provided.
	 * @param publicKey the {@link RSAPublicKey} and @Param privateKey the
	 * {@link RSAPrivateKey} to use for signing JWTs
	 * @return a {@link RsaKeyPairJwtEncoderBuilder}
	 * @since 7.0
	 */
	public static RsaKeyPairJwtEncoderBuilder withKeyPair(RSAPublicKey publicKey, RSAPrivateKey privateKey) {
		return new RsaKeyPairJwtEncoderBuilder(publicKey, privateKey);
	}

	/**
	 * Creates a builder for constructing a {@link NimbusJwtEncoder} using the provided.
	 * @param publicKey the {@link ECPublicKey} and @param privateKey the

View on GitHub (pinned to 96852e8860)