lcobucci/jwt · error · Lcobucci\JWT\Validation\ConstraintViolation

The token does not have the claim

Error message

The token does not have the claim "{claim}"

What it means

HasClaim asserts that the token contains the given custom claim; if the claim set has no such key, it throws ConstraintViolation with this message. It signals the expected claim is missing, not that its value was wrong.

Solutions

  1. Update the token issuer to always include the required claim
  2. Make the constraint optional / use Validator::assert multiple times with fallback handling
  3. Catch ConstraintViolation and treat missing claim as a valid-but-unprivileged token if the claim is truly optional

Example fix

// before (token payload lacking claim)
{"sub": "123"}
// after
{"sub": "123", "role": "admin"}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!$token instanceof UnencryptedToken || !$token->claims()->has('role')) {
    // handle missing claim before asserting
}

Try / catch

try {
    $validator->assert($token, new HasClaim('role'));
} catch (RequiredConstraintsViolated $e) {
    // claim absent; treat as unprivileged or reject
}

Prevention

When it happens

Trigger: (new HasClaim('role'))->assert($plainToken) where $plainToken->claims() does not contain the key 'role'.

Common situations: Tokens issued by an older version of the issuer that didn't add the claim yet; per-client tokens missing optional claims; environment-specific tokens (staging vs production issuers).

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


AI-assisted analysis of lcobucci/jwt@375813049c (2026-09-14). Data as JSON: /api/errors/74de05070138be22. Report an issue: GitHub.

Appendix: source

Thrown at src/Validation/Constraint/HasClaim.php:32

{
    /** @param non-empty-string $claim */
    public function __construct(private string $claim)
    {
        if (in_array($claim, Token\RegisteredClaims::ALL, true)) {
            throw CannotValidateARegisteredClaim::create($claim);
        }
    }

    public function assert(Token $token): void
    {
        if (! $token instanceof UnencryptedToken) {
            throw ConstraintViolation::error('You should pass a plain token', $this);
        }

        $claims = $token->claims();

        if (! $claims->has($this->claim)) {
            throw ConstraintViolation::error('The token does not have the claim "' . $this->claim . '"', $this);
        }
    }
}

View on GitHub (pinned to 375813049c)