spring-projects/spring-security · error · JwtEncodingException

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

Error message

Failed to encode the JWT due to signing error: Failed to create a JWS Signer -> + ex.getMessage()

What it means

NimbusJwtEncoder.createSigner() calls the nimbus-jose-jwt JWS signer factory to build a JWSSigner for the selected JWK and wraps any JOSEException in a JwtEncodingException. This fires before signing ever starts: the factory cannot construct a signer for the given key type/algorithm combination at all. It typically means the JWK's key type is incompatible with the requested JWS algorithm or the key material is invalid.

Solutions

  1. Check the wrapped exception via getCause(): it states why the signer could not be created (unsupported algorithm/key pair).
  2. Align the JwsAlgorithm in JwsHeader (or EncoderParameters claims) with the key type your JWKSource actually serves — inspect the JWK with jwk.getKeyType() and jwk.getAlgorithm().
  3. Rebuild the JWK ensuring required parameters exist: for RSAKey provide modulus+exponent (or KeyPair), for ECKey provide curve+point, for OctetSequenceKey provide a full-length secret.
  4. Test the JWK standalone with new NimbusRS256Signer / JWSAlgorithmFactory to confirm it can sign before wiring it into the JWKSource.

Example fix

// before
JWKSource<SecurityContext> jwkSource = (jwkSelector, ctx) ->
    List.of(rsaKey); // algorithm requested: ES256
// after
ECKey ecKey = new ECKeyGenerator(Curve.P_256).keyID("k1").generate();
JWKSource<SecurityContext> jwkSource = (jwkSelector, ctx) ->
    jwkSelector.select(List.of(ecKey)); // matches ES256
Defensive patterns

Strategy: validation

Validate before calling

// before registering the JWKSource
JWSAlgorithm alg = (JWSAlgorithm) jwsHeader.getAlgorithm();
if (!JWSAlgorithm.Family.SIGNATURE.contains(alg)
        || !jwk.getKeyType().getValue().equals(expectedKeyTypeFor(alg))) {
    throw new IllegalStateException("JWK type " + jwk.getKeyType() + " unsupported for " + alg);
}

Try / catch

try {
    return jwtEncoder.encode(parameters);
} catch (JwtEncodingException ex) {
    throw new TokenSigningException("Signer creation failed for JWK " + jwkId, ex.getCause());
}

Prevention

When it happens

Trigger: NimbusJwtEncoder.encode(...) where the JWKSource resolves a JWK that the JWSAlgorithmFactory cannot handle: e.g. requesting ES256 while the resolved JWK is an RSAKey, an OctetSequenceKey with an empty/invalid secret bytes, or a JWK missing required fields (no modulus/exponent, no EC curve parameter) so createJWSSigner throws.

Common situations: JWKSource returning keys of a different type than the configured jwsAlgorithm; hand-rolled JWK JSON parsed with missing parameters; OctetSequenceKey built with a null or too-short secret; changing the algorithm in JwtEncoderParameters without updating the keystore; loading keys from a vault/KMS where the export drops required fields.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

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

		}

		JwsHeader.Builder headersBuilder = JwsHeader.from(headers);
		if (!StringUtils.hasText(headers.getKeyId()) && StringUtils.hasText(jwk.getKeyID())) {
			headersBuilder.keyId(jwk.getKeyID());
		}
		if (!StringUtils.hasText(headers.getX509SHA256Thumbprint()) && jwk.getX509CertSHA256Thumbprint() != null) {
			headersBuilder.x509SHA256Thumbprint(jwk.getX509CertSHA256Thumbprint().toString());
		}

		return headersBuilder.build();
	}

	private static JWSSigner createSigner(JWK jwk) {
		try {
			return JWS_SIGNER_FACTORY.createJWSSigner(jwk);
		}
		catch (JOSEException ex) {
			throw new JwtEncodingException(String.format(ENCODING_ERROR_MESSAGE_TEMPLATE,
					"Failed to create a JWS Signer -> " + ex.getMessage()), ex);
		}
	}

	private static JWSHeader convert(JwsHeader headers) {
		JwsAlgorithm algorithm = headers.getAlgorithm();
		Assert.notNull(algorithm, "JWS header algorithm must not be null");
		JWSHeader.Builder builder = new JWSHeader.Builder(JWSAlgorithm.parse(algorithm.getName()));

		if (headers.getJwkSetUrl() != null) {
			builder.jwkURL(convertAsURI(JoseHeaderNames.JKU, headers.getJwkSetUrl()));
		}

		Map<String, Object> jwk = headers.getJwk();
		if (!CollectionUtils.isEmpty(jwk)) {
			try {
				builder.jwk(JWK.parse(jwk));
			}

View on GitHub (pinned to 96852e8860)