spring-projects/spring-security · error · JwtException

An error occurred while attempting to decode the Jwt: + ex.g

Error message

An error occurred while attempting to decode the Jwt: + ex.getMessage()

What it means

NimbusReactiveJwtDecoder.decode() catches JwtException and rethrows it unchanged, but any other RuntimeException during token parsing/processing is wrapped in a new JwtException with this message. It means an unexpected runtime problem (not a normal validation failure) occurred while decoding: malformed token text fed to nimbus-jose-jwt's SignedJWT.parse, JSON/serialization surprises, NPEs, or downstream reactive errors. Normal expired/invalid-signature errors surface as their own JwtValidationException/ BadJwtException instead.

Source

Thrown at oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java:179

					"An error occurred while attempting to decode the Jwt: " + ex.getMessage(), ex));
		}
	}

	private Mono<Jwt> decode(JWT parsedToken) {
		try {
			// @formatter:off
			return this.jwtProcessor.convert(parsedToken)
					.map((set) -> createJwt(parsedToken, set))
					.map(this::validateJwt)
					.onErrorMap((ex) -> !(ex instanceof IllegalStateException) && !(ex instanceof JwtException),
							(ex) -> new JwtException("An error occurred while attempting to decode the Jwt: ", ex));
			// @formatter:on
		}
		catch (JwtException ex) {
			throw ex;
		}
		catch (RuntimeException ex) {
			throw new JwtException("An error occurred while attempting to decode the Jwt: " + ex.getMessage(), ex);
		}
	}

	private Jwt createJwt(JWT parsedJwt, JWTClaimsSet jwtClaimsSet) {
		try {
			Map<String, Object> headers = new LinkedHashMap<>(parsedJwt.getHeader().toJSONObject());
			Map<String, Object> claims = this.claimSetConverter.convert(jwtClaimsSet.getClaims());
			return Jwt.withTokenValue(parsedJwt.getParsedString())
				.headers((h) -> h.putAll(headers))
				.claims((c) -> c.putAll(claims))
				.build();
		}
		catch (Exception ex) {
			throw new BadJwtException("An error occurred while attempting to decode the Jwt: " + ex.getMessage(), ex);
		}
	}

	private Jwt validateJwt(Jwt jwt) {

View on GitHub (pinned to 96852e8860)

Solutions

  1. Log the received token's structure (header claims via getClaims()) before decoding — confirm it has three dot-separated base64url segments.
  2. Inspect getCause(): the original RuntimeException pinpoints the real failure (parse error, NPE, network fetch of the JWK set).
  3. Verify the client is not sending an opaque token; if it is, use an OpaqueTokenIntrospector instead of NimbusReactiveJwtDecoder.
  4. Check the jwkSetUri/jwkSource endpoint returns valid JWK Set JSON (application/json) and is reachable from the decoder.

Example fix

// before
jwtDecoder.decode(rawToken); // rawToken may be opaque
// after
if (rawToken.chars().filter(c -> c == '.').count() == 2) {
    jwtDecoder.decode(rawToken);
} else {
    return Mono.error(new InvalidBearerTokenException("Token is not a JWT"));
}
Defensive patterns

Strategy: try-catch

Validate before calling

// reject obviously non-JWT tokens before calling decode
static boolean looksLikeJwt(String token) {
    return token != null && token.chars().filter(c -> c == '.').count() == 2;
}

Try / catch

try {
    return jwtDecoder.decode(token).block();
} catch (BadJwtException ex) {
    throw new InvalidBearerTokenException("Malformed token");
} catch (JwtValidationException ex) {
    throw new OAuth2TokenValidationException("Token failed validation", ex);
} catch (JwtException ex) {
    // message begins "An error occurred while attempting to decode the Jwt"
    logger.warn("Unexpected decode failure", ex.getCause());
    throw new InvalidBearerTokenException("Token could not be processed");
}

Prevention

When it happens

Trigger: decode(token) with a token string that is not valid compact JWS/JWE serialization (empty, truncated, or arbitrary text), a token whose header/claims JSON breaks parsing, or a custom JwtDecoder configuration (e.g. misconfigured JWKSource/processor) throwing NPE/IllegalStateException during processing.

Common situations: Sending a raw access token from a non-JWT flow (opaque token) to a JWT decoder; tokens truncated by proxies or logging round-trips; JWK set endpoint returning HTML/error pages that break key fetching; missing clock/validator config causing NPEs in older Spring Security versions; base64url-corrupted tokens stored in cookies.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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