lcobucci/jwt · error · RequiredConstraintsViolated
Required constraints violated
Error message
Required constraints violated
What it means
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.
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.
Example fix
// before
$validator->assert($token, new SignedWith($signer, $key)); // generic 'Required constraints violated'
// after
try {
$validator->assert($token, new SignedWith($signer, $key), new StrictValidAt($clock));
} catch (RequiredConstraintsViolated $e) {
foreach ($e->getViolations() as $violation) {
error_log($violation->getMessage()); // e.g. 'The token was issued in the future'
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check constraints yourself and log which one would fail
$violations = [];
$validator = new Lcobucci\JWT\Validation\Validator();
foreach ($constraints as $constraint) {
if (!$constraint->assert($token)) { // validate() variant collects instead of throwing
$violations[] = get_class($constraint);
}
}
// if $violations is non-empty, assert() would throw RequiredConstraintsViolated Type guard
function passesAllConstraints(Lcobucci\JWT\Token $token, Lcobucci\JWT\Validation\Validator $v, Lcobucci\JWT\Validation\Constraint ...$constraints): bool
{
return $v->validate($token, ...$constraints); // validate() returns bool, never throws
} Try / catch
use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
try {
$validator->assert($token, ...$constraints);
} catch (RequiredConstraintsViolated $e) {
foreach ($e->getViolations() as $violation) {
// inspect $violation->getMessage() to branch on expired/signature/claims failures
}
} Prevention
- 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.
When it happens
Trigger: 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().
Common situations: 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().
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- No constraint given.
- The token was issued in the future
- Error while decoding from Base64Url, invalid base64…
- Builder#withClaim() is meant to be used for non-registered…
- The JWT string is missing the Header part
AI-assisted analysis of lcobucci/jwt@375813049c (2026-09-14).
Data as JSON: /api/errors/562e76a2c2a27351.
Report an issue: GitHub.
Appendix: source
Thrown at src/Validation/Validator.php:23
use Lcobucci\JWT\Token;
final readonly class Validator implements \Lcobucci\JWT\Validator
{
public function assert(Token $token, Constraint ...$constraints): void
{
if ($constraints === []) {
throw new NoConstraintsGiven('No constraint given.');
}
$violations = [];
foreach ($constraints as $constraint) {
$this->checkConstraint($constraint, $token, $violations);
}
if ($violations !== []) {
throw RequiredConstraintsViolated::fromViolations(...$violations);
}
}
/** @param ConstraintViolation[] $violations */
private function checkConstraint(
Constraint $constraint,
Token $token,
array &$violations,
): void {
try {
$constraint->assert($token);
} catch (ConstraintViolation $e) {
$violations[] = $e;
}
}
public function validate(Token $token, Constraint ...$constraints): bool
{View on GitHub (pinned to 375813049c)