{"record":{"id":"024521a23320cb1d","repo":"jwtk/jjwt","slug":"missing-expectedclaimname-claim-expected-valu","errorCode":null,"errorMessage":"Missing '<expectedClaimName>' claim. Expected value: <expectedClaimValue>","messagePattern":"Missing '<expectedClaimName>' claim\\. Expected value: <expectedClaimValue>","errorType":"exception","errorClass":"MissingClaimException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java","lineNumber":756,"sourceCode":"            if (expectedClaimValue instanceof Date) {\n                try {\n                    actualClaimValue = claims.get(expectedClaimName, Date.class);\n                } catch (Exception e) {\n                    String msg = \"JWT Claim '\" + expectedClaimName + \"' was expected to be a Date, but its value \" +\n                            \"cannot be converted to a Date using current heuristics.  Value: \" + actualClaimValue;\n                    throw new IncorrectClaimException(header, claims, expectedClaimName, expectedClaimValue, msg);\n                }\n            }\n\n            if (actualClaimValue == null) {\n                boolean collection = expectedClaimValue instanceof Collection;\n                String msg = \"Missing '\" + expectedClaimName + \"' claim. Expected value\";\n                if (collection) {\n                    msg += \"s: \" + expectedClaimValue;\n                } else {\n                    msg += \": \" + expectedClaimValue;\n                }\n                throw new MissingClaimException(header, claims, expectedClaimName, expectedClaimValue, msg);\n            } else if (expectedClaimValue instanceof Collection) {\n                Collection<?> expectedValues = (Collection<?>) expectedClaimValue;\n                Collection<?> actualValues = actualClaimValue instanceof Collection ? (Collection<?>) actualClaimValue :\n                        Collections.setOf(actualClaimValue);\n                for (Object expectedValue : expectedValues) {\n                    if (!Collections.contains(actualValues.iterator(), expectedValue)) {\n                        String msg = String.format(MISSING_EXPECTED_CLAIM_VALUE_MESSAGE_TEMPLATE,\n                                expectedValue, expectedClaimName, actualValues);\n                        throw new IncorrectClaimException(header, claims, expectedClaimName, expectedClaimValue, msg);\n                    }\n                }\n            } else if (!expectedClaimValue.equals(actualClaimValue)) {\n                String msg = String.format(INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE,\n                        expectedClaimName, expectedClaimValue, actualClaimValue);\n                throw new IncorrectClaimException(header, claims, expectedClaimName, expectedClaimValue, msg);\n            }\n        }\n    }","sourceCodeStart":738,"sourceCodeEnd":774,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java#L738-L774","documentation":"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.","triggerScenarios":"Calling DefaultJwtParserBuilder.require(\"aud\", value) (or requireExpiration, requireIssuedAt, etc.) and then parsing a JWT that does not contain that claim name at all.","commonSituations":"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.","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."],"exampleFix":"// before\nJwts.parser().require(\"tenant\", \"acme\").verifyWith(key).build().parse(jwt); // token lacks 'tenant'\n// after\n// producer:\nString jwt = Jwts.builder().claim(\"tenant\", \"acme\").signWith(key).compact();\n// or consumer: drop the requirement if optional\nJwts.parser().verifyWith(key).build().parse(jwt);","handlingStrategy":"validation","validationCode":"io.jsonwebtoken.Claims c = Jwts.parser().build().parseUnsecuredClaims(jwt).getPayload();\nif (!c.containsKey(\"tenant\")) {\n    throw new IllegalStateException(\"Token lacks required claim 'tenant'\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    claims = Jwts.parser().require(\"tenant\", \"acme\").verifyWith(key).build().parseSignedClaims(jwt).getPayload();\n} catch (io.jsonwebtoken.MissingClaimException e) {\n    // reject token; log e.getClaimName()\n}","preventionTips":["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"],"tags":["jwt","claims-validation","missing-claim"],"backgroundTag":"jwt-claim-validation-failed","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}