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

You should pass a plain token

Error message

You should pass a plain token

What it means

HasClaimWithValue requires an UnencryptedToken to read its claim set. Passing any other Token type to assert() throws ConstraintViolation 'You should pass a plain token'. Encrypted/opaque tokens cannot have their claims inspected.

Solutions

  1. Decrypt the token (or obtain the plain signed token) before validating claims
  2. Guard with instanceof UnencryptedToken before running the constraint
  3. Separate validation flows for encrypted vs plain tokens

Example fix

// before
$constraint->assert($jweToken);
// after
if ($token instanceof UnencryptedToken) {
    $constraint->assert($token);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!$token instanceof \Jose\Component\Core\UnencryptedToken) {
    throw new \LogicException('Value constraint needs a plain 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 HasClaimWithValue('role', 'admin'));
} catch (ConstraintViolationException $e) {
    // non-plain token or value mismatch; reject
}

Prevention

When it happens

Trigger: (new HasClaimWithValue('role', 'admin'))->assert($token) where $token is not an instance of UnencryptedToken (e.g. an encrypted JWE token).

Common situations: Running the same validator over encrypted and plain tokens; a decryption step failing silently upstream so an opaque token reaches the validator; passing the wrong variable to assert().

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/b538e208de6f1861. Report an issue: GitHub.

Appendix: source

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

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

use function in_array;

final readonly class HasClaimWithValue implements Constraint
{
    /** @param non-empty-string $claim */
    public function __construct(private string $claim, private mixed $expectedValue)
    {
        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);
        }

        if ($claims->get($this->claim) !== $this->expectedValue) {
            throw ConstraintViolation::error(
                'The claim "' . $this->claim . '" does not have the expected value',
                $this,
            );
        }
    }
}

View on GitHub (pinned to 375813049c)