jwtk/jjwt · error · IncorrectClaimException
Missing expected '<expectedValue>' value in '<expectedClaimN
Error message
Missing expected '<expectedValue>' value in '<expectedClaimName>' claim <actualValues>.
What it means
Thrown as IncorrectClaimException when a claim required via require(claimName, collection) is present but does not contain one of the expected values. JJWT converts the actual claim value to a collection (using it directly if it is already a Collection, otherwise wrapping it in a set) and checks that every expected value is contained in it.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java:765
if (actualClaimValue == null) {
boolean collection = expectedClaimValue instanceof Collection;
String msg = "Missing '" + expectedClaimName + "' claim. Expected value";
if (collection) {
msg += "s: " + expectedClaimValue;
} else {
msg += ": " + expectedClaimValue;
}
throw new MissingClaimException(header, claims, expectedClaimName, expectedClaimValue, msg);
} else if (expectedClaimValue instanceof Collection) {
Collection<?> expectedValues = (Collection<?>) expectedClaimValue;
Collection<?> actualValues = actualClaimValue instanceof Collection ? (Collection<?>) actualClaimValue :
Collections.setOf(actualClaimValue);
for (Object expectedValue : expectedValues) {
if (!Collections.contains(actualValues.iterator(), expectedValue)) {
String msg = String.format(MISSING_EXPECTED_CLAIM_VALUE_MESSAGE_TEMPLATE,
expectedValue, expectedClaimName, actualValues);
throw new IncorrectClaimException(header, claims, expectedClaimName, expectedClaimValue, msg);
}
}
} else if (!expectedClaimValue.equals(actualClaimValue)) {
String msg = String.format(INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE,
expectedClaimName, expectedClaimValue, actualClaimValue);
throw new IncorrectClaimException(header, claims, expectedClaimName, expectedClaimValue, msg);
}
}
}
@SuppressWarnings("deprecation")
@Override
public <T> T parse(CharSequence compact, JwtHandler<T> handler) {
return parse(compact, Payload.EMPTY).accept(handler);
}
private Jwt<?, ?> parse(CharSequence compact, Payload unencodedPayload) {
Assert.hasText(compact, "JWT String argument cannot be null or empty.");View on GitHub (pinned to fb71496164)
Solutions
- Update the expected collection in require(...) to match what the issuer actually emits (decode the token to inspect the real values).
- Fix the token issuer to include the expected value in the claim.
- If the consumer registered for multiple audiences, add its own identifier to the issuer's aud list.
- Log the token's actual claim values (or catch IncorrectClaimException and read its message) to diagnose the exact mismatch.
Example fix
// before
Jwts.parser().require("aud", List.of("api-prod")).verifyWith(key).build().parse(jwt); // token aud=["api-staging"]
// after
Jwts.parser().require("aud", List.of("api-prod", "api-staging")).verifyWith(key).build().parse(jwt);
// or fix issuer: Jwts.builder().audience().add("api-prod").and()... Defensive patterns
Strategy: validation
Validate before calling
io.jsonwebtoken.Claims c = Jwts.parser().build().parseUnsecuredClaims(jwt).getPayload();
java.util.List<?> aud = c.get("aud", java.util.List.class);
java.util.Set<String> expected = java.util.Set.of("api-prod");
if (aud == null || java.util.Collections.disjoint(aud, expected)) {
throw new IllegalStateException("aud mismatch: " + aud);
} Try / catch
try {
claims = Jwts.parser().require("aud", expectedAudiences).verifyWith(key).build().parseSignedClaims(jwt).getPayload();
} catch (io.jsonwebtoken.IncorrectClaimException e) {
// message names the missing expected value and actual values
} Prevention
- Keep accepted audience/scope lists in configuration, updated alongside issuer changes
- Use environment-specific expected values (staging vs prod)
- Decode a real producer token before freezing the expected set
- Catch IncorrectClaimException and log actual vs expected for diagnostics
When it happens
Trigger: parser.require("aud", Set.of("audience-a","audience-b")) where the token's 'aud' claim exists but lacks one of the expected values — e.g. aud is 'audience-a' only, or contains values not in the expected set.
Common situations: Audience mismatch between issuer and consumer configurations (wrong client ID / audience registered); role/scope lists changed on the issuer but expected sets on the consumer are stale; tokens minted for a different environment (prod aud vs staging verifier).
Related errors
- JWT Claim '<expectedClaimName>' was expected to be a Date, b
- Missing '<expectedClaimName>' claim. Expected value: <expect
- Expected <expectedClaimName> claim to be: <expectedClaimValu
- Unexpected unsecured Claims JWT.
- Unexpected content JWS.
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/7f6c928d79c04ec6.
Report an issue: GitHub.