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
- Only run this constraint on decrypted/plain tokens; decrypt or convert the token first
- Check $token instanceof UnencryptedToken before adding the constraint to a validator
- 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
- Decrypt tokens before running claim constraints
- Keep separate validators for JWE and JWS flows
- Type-check tokens before adding constraints
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
- You should pass a plain token
- The claim " " is a registered claim, another constraint…
- The claim " " is a registered claim, another constraint…
- You should pass a plain token
- No constraint given.
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)