lcobucci/jwt · error · ConstraintViolation
This constraint was only usable until
Error message
This constraint was only usable until <RFC3339 date>
What it means
SignedWithUntilDate is a decorator constraint that enforces a usability deadline: it holds a validUntil date and a clock, and before delegating it checks whether the deadline has passed. If the configured date is in the past, it throws with the RFC3339 date it stopped being usable. This lets you retire old signing keys/constraints on a schedule.
Solutions
- Update the validUntil date (or remove the decorator) if the constraint should still be usable
- Verify the system clock / Clock implementation is correct and not skewed
- Reissue tokens under a constraint set that is still within its validity window
- If this expiry was intentional, treat it as expected behavior and reject/refresh tokens client-side
Example fix
// before
new SignedWithUntilDate(new SignedWith(new Sha256(), $key), new DateTimeImmutable('2024-01-01 00:00:00'));
// after
new SignedWithUntilDate(new SignedWith(new Sha256(), $key), new DateTimeImmutable('2026-12-31 23:59:59')); Defensive patterns
Strategy: validation
Validate before calling
if ($constraintValidUntil < (new DateTimeImmutable())) {
throw new RuntimeException('SignedWithUntilDate expired; update constraint configuration');
} Type guard
null
Try / catch
try {
$validator->assert($token, $untilDateConstraint);
} catch (ConstraintViolation $e) {
// swap to current constraint set / trigger key rotation procedure
} Prevention
- Tie constraint validity dates to deployment/rotation automation so they are renewed
- Monitor upcoming expiry of key constraints and alert before they lapse
- Verify server clocks are NTP-synced
When it happens
Trigger: Using a SignedWithUntilDate constraint whose validUntil date is earlier than clock->now() — calling Validator::assert($token, new SignedWithUntilDate(...)) after the configured expiry, regardless of whether the token signature itself is valid.
Common situations: Long-lived deployments where a temporary key-rotation constraint expired but code was not updated; clock skew or misconfigured system time making 'now' appear past the deadline; intentionally sunsetting a token set but still receiving old tokens from cached clients.
Related errors
- The token is expired
- No constraint given.
- The claim " " is a registered claim, another constraint…
- You should pass a plain token
- The token does not have the claim
AI-assisted analysis of lcobucci/jwt@375813049c (2026-09-14).
Data as JSON: /api/errors/6940f19eff2c6243.
Report an issue: GitHub.
Appendix: source
Thrown at src/Validation/Constraint/SignedWithUntilDate.php:38
Signer $signer,
Signer\Key $key,
private DateTimeImmutable $validUntil,
?ClockInterface $clock = null,
) {
$this->verifySignature = new SignedWith($signer, $key);
$this->clock = $clock ?? new class () implements ClockInterface {
public function now(): DateTimeImmutable
{
return new DateTimeImmutable();
}
};
}
public function assert(Token $token): void
{
if ($this->validUntil < $this->clock->now()) {
throw ConstraintViolation::error(
'This constraint was only usable until '
. $this->validUntil->format(DateTimeInterface::RFC3339),
$this,
);
}
$this->verifySignature->assert($token);
}
}
View on GitHub (pinned to 375813049c)