lcobucci/jwt · error · Lcobucci\JWT\Validation\Constraint\CannotValidateARegisteredClaim

The claim " " is a registered claim, another constraint…

Error message

The claim "{claim}" is a registered claim, another constraint must be used to validate its value

What it means

HasClaim is intended only for custom (private) claims; registered claims such as iss, sub, aud, exp, nbf, iat, jti have dedicated constraints that know how to validate their values. Constructing HasClaim with a registered claim name immediately throws CannotValidateARegisteredClaim. This steers you to the correct, stricter constraint.

Solutions

  1. Use the dedicated constraint for that claim (e.g. IssuedBy, ValidAt, IdentifiedBy, RelatedTo, PermittedFor)
  2. If you only need presence of a registered claim, read $token->claims()->get('iss') directly and assert yourself
  3. Register the custom claim name instead if it was accidentally named like a registered claim

Example fix

// before
$constraint = new HasClaim('iss');
// after
$constraint = new IssuedBy('https://issuer.example.com');
Defensive patterns

Strategy: type-guard

Validate before calling

if (in_array($claimName, \Jose\Component\Signature\Token\RegisteredClaims::ALL, true)) {
    // use the dedicated constraint instead
}

Type guard

function isCustomClaim(string $claim): bool {
    return !in_array($claim, Token\RegisteredClaims::ALL, true);
}

Try / catch

try {
    $constraint = new HasClaim('my_claim');
} catch (CannotValidateARegisteredClaim $e) {
    // fall back to the dedicated registered-claim constraint
}

Prevention

When it happens

Trigger: new HasClaim('iss'), new HasClaim('sub'), new HasClaim('aud'), new HasClaim('exp'), new HasClaim('nbf'), new HasClaim('iat'), new HasClaim('jti') (any entry of Token\RegisteredClaims::ALL).

Common situations: Developers unfamiliar with the dedicated constraints reaching for the generic HasClaim to check standard claims like issuer or expiry; migrating code that previously just checked claim presence.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

<?php
declare(strict_types=1);

namespace Lcobucci\JWT\Validation\Constraint;

use Lcobucci\JWT\Token;
use Lcobucci\JWT\UnencryptedToken;
use Lcobucci\JWT\Validation\Constraint;
use Lcobucci\JWT\Validation\ConstraintViolation;

use function in_array;

final readonly class HasClaim implements Constraint
{
    /** @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)