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
- Use the dedicated constraint for that claim (e.g. IssuedBy, ValidAt, IdentifiedBy, RelatedTo, PermittedFor)
- If you only need presence of a registered claim, read $token->claims()->get('iss') directly and assert yourself
- 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
- Consult Token\RegisteredClaims::ALL before using generic constraints
- Map registered claims to their dedicated constraints (IssuedBy, ValidAt, ...)
- Wrap constraint construction in a factory that picks the right class
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
- The claim " " is a registered claim, another constraint…
- You should pass a plain token
- You should pass a plain token
- No constraint given.
- The token does not have the claim
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)