{"record":{"id":"08fd5825909e3b58","repo":"lcobucci/jwt","slug":"the-token-does-not-have-the-claim-claim-hasclaimwithvalue","errorCode":null,"errorMessage":"The token does not have the claim \"{claim}\"","messagePattern":"The token does not have the claim \"(.+?)\"","errorType":"exception","errorClass":"Lcobucci\\JWT\\Validation\\ConstraintViolation","httpStatus":null,"severity":"error","filePath":"src/Validation/Constraint/HasClaimWithValue.php","lineNumber":32,"sourceCode":"{\n    /** @param non-empty-string $claim */\n    public function __construct(private string $claim, private mixed $expectedValue)\n    {\n        if (in_array($claim, Token\\RegisteredClaims::ALL, true)) {\n            throw CannotValidateARegisteredClaim::create($claim);\n        }\n    }\n\n    public function assert(Token $token): void\n    {\n        if (! $token instanceof UnencryptedToken) {\n            throw ConstraintViolation::error('You should pass a plain token', $this);\n        }\n\n        $claims = $token->claims();\n\n        if (! $claims->has($this->claim)) {\n            throw ConstraintViolation::error('The token does not have the claim \"' . $this->claim . '\"', $this);\n        }\n\n        if ($claims->get($this->claim) !== $this->expectedValue) {\n            throw ConstraintViolation::error(\n                'The claim \"' . $this->claim . '\" does not have the expected value',\n                $this,\n            );\n        }\n    }\n}\n","sourceCodeStart":14,"sourceCodeEnd":43,"githubUrl":"https://github.com/lcobucci/jwt/blob/375813049c24c7111bda8b6884c57b071ceb2fe7/src/Validation/Constraint/HasClaimWithValue.php#L14-L43","documentation":"HasClaimWithValue first checks the claim exists; if the claim key is absent from the token's claim set it throws ConstraintViolation 'The token does not have the claim ...'. This happens before any value comparison.","triggerScenarios":"(new HasClaimWithValue('role', 'admin'))->assert($plainToken) where the claim 'role' is not present in $plainToken->claims().","commonSituations":"Legacy tokens issued before the claim was introduced; tokens from a different issuer/tenant that omit the claim; typo in the claim name between issuer and validator.","solutions":["Ensure the issuer always emits the claim","Fix claim-name typos so issuer and validator agree","Catch ConstraintViolation and handle absence explicitly if the claim is optional"],"exampleFix":"// before\n{\"sub\": \"123\"}\n// after\n{\"sub\": \"123\", \"role\": \"admin\"}","handlingStrategy":"try-catch","validationCode":"if (!$token->claims()->has('role')) {\n    // handle absence before value assertion\n}","typeGuard":null,"tryCatchPattern":"try {\n    $validator->assert($token, new HasClaimWithValue('role', 'admin'));\n} catch (RequiredConstraintsViolated $e) {\n    // claim missing; reject or degrade\n}","preventionTips":["Keep issuer and validator claim names in a shared constant/config","Add integration tests with real issued tokens","Reject tokens lacking mandatory claims at ingestion"],"tags":["jwt","validation","claims","missing-claim"],"backgroundTag":"schema-validation-failed","analyzedSha":"375813049c24c7111bda8b6884c57b071ceb2fe7","analyzedAt":"2026-09-14T11:12:28.004Z","contentChangedAt":"2026-09-14T11:12:28.004Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}