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

You should pass a plain token

Error message

You should pass a plain token

What it means

HasClaim can only inspect the claim set of a plain (unencrypted) JWT. If assert() is handed a Token that is not an UnencryptedToken — e.g. a signed/encrypted token object that doesn't expose claims — it raises ConstraintViolation 'You should pass a plain token'. This guards against attempting claim inspection on opaque tokens.

Solutions

  1. Only run this constraint on decrypted/plain tokens; decrypt or convert the token first
  2. Check $token instanceof UnencryptedToken before adding the constraint to a validator
  3. Split validation into two paths: one for encrypted tokens, one for plain tokens

Example fix

// before
(new Validator())->assert($someEncryptedToken, new HasClaim('role'));
// after
if ($token instanceof UnencryptedToken) {
    (new Validator())->assert($token, new HasClaim('role'));
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!$token instanceof \Jose\Component\Core\UnencryptedToken) {
    throw new \LogicException('Claim constraints require a plain (unencrypted) token');
}

Type guard

function isPlainToken(\Jose\Component\Core\TokenInterface $t): bool {
    return $t instanceof \Jose\Component\Core\UnencryptedToken;
}

Try / catch

try {
    $validator->assert($token, new HasClaim('role'));
} catch (RequiredConstraintsViolated|ConstraintViolationException $e) {
    // includes non-plain-token violations; handle
}

Prevention

When it happens

Trigger: Calling (new HasClaim('custom'))->assert($token) where $token is not an UnencryptedToken, e.g. when a Validator is run against an encrypted JWE token or a Token subclass without claim access.

Common situations: Running a shared validator configuration over both JWS and JWE tokens; passing the wrong token variable into assert(); pipelines where decryption step was skipped.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

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)