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
- Decrypt the token (or obtain the plain signed token) before validating claims
- Guard with instanceof UnencryptedToken before running the constraint
- 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
- Decrypt before claim validation
- Assert token type before building the validator pipeline
- Document that claim constraints apply only to JWS tokens
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
- 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/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)