{"record":{"id":"562e76a2c2a27351","repo":"lcobucci/jwt","slug":"required-constraints-violated","errorCode":null,"errorMessage":"Required constraints violated","messagePattern":"Required constraints violated","errorType":"validation","errorClass":"RequiredConstraintsViolated","httpStatus":null,"severity":"error","filePath":"src/Validation/Validator.php","lineNumber":23,"sourceCode":"\nuse Lcobucci\\JWT\\Token;\n\nfinal readonly class Validator implements \\Lcobucci\\JWT\\Validator\n{\n    public function assert(Token $token, Constraint ...$constraints): void\n    {\n        if ($constraints === []) {\n            throw new NoConstraintsGiven('No constraint given.');\n        }\n\n        $violations = [];\n\n        foreach ($constraints as $constraint) {\n            $this->checkConstraint($constraint, $token, $violations);\n        }\n\n        if ($violations !== []) {\n            throw RequiredConstraintsViolated::fromViolations(...$violations);\n        }\n    }\n\n    /** @param ConstraintViolation[] $violations */\n    private function checkConstraint(\n        Constraint $constraint,\n        Token $token,\n        array &$violations,\n    ): void {\n        try {\n            $constraint->assert($token);\n        } catch (ConstraintViolation $e) {\n            $violations[] = $e;\n        }\n    }\n\n    public function validate(Token $token, Constraint ...$constraints): bool\n    {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/lcobucci/jwt/blob/375813049c24c7111bda8b6884c57b071ceb2fe7/src/Validation/Validator.php#L5-L41","documentation":"This is lcobucci/jwt's aggregate validation error. Validator::assert runs each given constraint against the token, collecting ConstraintViolation objects; if any constraint failed, it throws RequiredConstraintsViolated::fromViolations(...). This exception (a subclass of the constraint-violation family) carries all individual violations, unlike Validator::validate() which returns false silently.","triggerScenarios":"Any call to (new Validator())->assert($token, ...constraints...) where at least one constraint produces a violation: e.g. assert($token, new SignedWith($signer, $key)) with a wrong key, StrictValidAt with a future iat or expired exp, IdentifiedBy with a mismatching jti, or an empty/failed constraint set — the exception wraps the underlying ConstraintViolation(s) and its message stays generic ('Required constraints violated') while details live on getViolations().","commonSituations":"Verifying tokens signed with a rotated/changed secret key; expired or not-yet-valid tokens checked with StrictValidAt/ValidAt; tokens missing required claims (iat, exp, jti); migrating library versions where claim handling became stricter (e.g. lcobucci/jwt 4.x/5.x behavior changes); callers inspecting only the top-level message instead of getViolations().","solutions":["Catch lcobucci\\jwt\\Validation\\RequiredConstraintsViolated and call getViolations() to see which constraint(s) actually failed before deciding on a fix.","Verify the signing key/signer passed to SignedWith matches the one used to sign the token (algorithm and key material).","Check the token's time claims: ensure exp is in the future, iat/nbf are not in the future relative to your clock, and enable leeway (DateInterval) if clock skew exists.","Re-derive or re-issue the token if required claims (aud, jti, sub, custom constraints) don't match expectations; use UnsupportedHeaderExceptions/constraint unit tests to validate your constraint set."],"exampleFix":"// before\n$validator->assert($token, new SignedWith($signer, $key)); // generic 'Required constraints violated'\n\n// after\ntry {\n    $validator->assert($token, new SignedWith($signer, $key), new StrictValidAt($clock));\n} catch (RequiredConstraintsViolated $e) {\n    foreach ($e->getViolations() as $violation) {\n        error_log($violation->getMessage()); // e.g. 'The token was issued in the future'\n    }\n}","handlingStrategy":"try-catch","validationCode":"// pre-check constraints yourself and log which one would fail\n$violations = [];\n$validator = new Lcobucci\\JWT\\Validation\\Validator();\nforeach ($constraints as $constraint) {\n    if (!$constraint->assert($token)) { // validate() variant collects instead of throwing\n        $violations[] = get_class($constraint);\n    }\n}\n// if $violations is non-empty, assert() would throw RequiredConstraintsViolated","typeGuard":"function passesAllConstraints(Lcobucci\\JWT\\Token $token, Lcobucci\\JWT\\Validation\\Validator $v, Lcobucci\\JWT\\Validation\\Constraint ...$constraints): bool\n{\n    return $v->validate($token, ...$constraints); // validate() returns bool, never throws\n}","tryCatchPattern":"use Lcobucci\\JWT\\Validation\\RequiredConstraintsViolated;\n\ntry {\n    $validator->assert($token, ...$constraints);\n} catch (RequiredConstraintsViolated $e) {\n    foreach ($e->getViolations() as $violation) {\n        // inspect $violation->getMessage() to branch on expired/signature/claims failures\n    }\n}","preventionTips":["Prefer Validator::validate() (boolean) when you only need pass/fail; reserve assert() for when you want detailed violations.","Always call getViolations() on RequiredConstraintsViolated — the top message is generic by design.","Keep signing keys in sync (key rotation) and verify the SignedWith algorithm matches the token's header alg.","Add leeway to time-based constraints and ensure server clocks are NTP-synchronized to avoid false constraint failures."],"tags":["jwt","validation","php","constraints"],"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"}