jwtk/jjwt · error · MissingClaimException
Missing ' ' claim. Expected value
Error message
Missing '<expectedClaimName>' claim. Expected value: <expectedClaimValue>
What it means
Thrown as MissingClaimException when a required claim configured via parser.require(claimName, expectedValue) is entirely absent from the parsed JWT's claims set. JJWT only checks this during parse when claim requirements were registered on the builder.
Solutions
- Fix the token producer to include the required claim.
- Remove or correct the require(...) call if the claim is genuinely optional.
- Check the claim name spelling against what the issuer actually emits (decode the payload to verify).
- Coordinate claim requirements across services; version the token schema if producers and consumers deploy independently.
Example fix
// before
Jwts.parser().require("tenant", "acme").verifyWith(key).build().parse(jwt); // token lacks 'tenant'
// after
// producer:
String jwt = Jwts.builder().claim("tenant", "acme").signWith(key).compact();
// or consumer: drop the requirement if optional
Jwts.parser().verifyWith(key).build().parse(jwt); Defensive patterns
Strategy: validation
Validate before calling
io.jsonwebtoken.Claims c = Jwts.parser().build().parseUnsecuredClaims(jwt).getPayload();
if (!c.containsKey("tenant")) {
throw new IllegalStateException("Token lacks required claim 'tenant'");
} Try / catch
try {
claims = Jwts.parser().require("tenant", "acme").verifyWith(key).build().parseSignedClaims(jwt).getPayload();
} catch (io.jsonwebtoken.MissingClaimException e) {
// reject token; log e.getClaimName()
} Prevention
- Share a claim-schema contract between issuer and consumers
- Decode a sample token from the producer and verify all required claim names exist
- Keep claim names in a shared constants class to avoid typos
- Write integration tests using tokens from the real producer
When it happens
Trigger: Calling DefaultJwtParserBuilder.require("aud", value) (or requireExpiration, requireIssuedAt, etc.) and then parsing a JWT that does not contain that claim name at all.
Common situations: Verifier expects an 'aud'/'iss'/'role' claim the token producer never set; tokens issued by an older version of the producing service lacking newly-required claims; copy-pasted require() calls referencing misspelled claim names.
Related errors
- Expected claim to be: , but was: .
- JWT Claim ' ' was expected to be a Date, but its value…
- Missing expected ' ' value in ' ' claim .
- 'b64' Unencoded payload option has been specified, but…
- Both a 'signingKeyResolver and a 'verifyWith' key cannot be…
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/024521a23320cb1d.
Report an issue: GitHub.
Appendix: source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java:756
if (expectedClaimValue instanceof Date) {
try {
actualClaimValue = claims.get(expectedClaimName, Date.class);
} catch (Exception e) {
String msg = "JWT Claim '" + expectedClaimName + "' was expected to be a Date, but its value " +
"cannot be converted to a Date using current heuristics. Value: " + actualClaimValue;
throw new IncorrectClaimException(header, claims, expectedClaimName, expectedClaimValue, msg);
}
}
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);
}
}
}View on GitHub (pinned to fb71496164)