Invalid JWT Token
Permalink to this error- Error code
- AUTH_TOKEN_INVALID
- HTTP status
- HTTP 401
- Severity
- Client fault
- Retry policy
- Not retryable
- Log level
- log: warning
The Authorization header carried a bearer token that could not be decoded or whose signature did not verify against the configured public key.
Why it happens
The JWT authenticator decodes the token before the firewall creates a token storage entry. Any structural or cryptographic failure aborts authentication and the entry point converts the AuthenticationException into a 401 response.
Common causes
- Token was signed with a key pair that no longer matches JWT_PUBLIC_KEY (key rotated, or dev keys used against prod).
- Token string was truncated, URL-encoded twice, or wrapped in quotes by the client.
- The header used a scheme other than Bearer, so the raw value was parsed as a token.
- The payload was hand-crafted in a test and is missing the configured user identity claim.
How to fix it
- 1
Verify the key pair the application actually loaded
Compare the fingerprint of the private key that issued the token with the public key resolved at runtime. A passphrase mismatch fails the same way as a wrong key.
bash php bin/console lexik:jwt:check-config php bin/console debug:config lexik_jwt_authentication - 2
Confirm the header shape on the client
The scheme is case sensitive and a single space separates it from the token.
http Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9... - 3
Inspect the decode failure reason instead of guessing
JWTDecodeFailureException exposes a reason constant. Log it in the failure handler so invalid-signature is never confused with expired.
php use Lexik\Bundle\JWTAuthenticationBundle\Exception\JWTDecodeFailureException; if ($exception instanceof JWTDecodeFailureException) { $this->logger->warning('JWT decode failed', [ 'reason' => $exception->getReason(), // invalid_token | unverified_token | expired_token ]); }
Example request or scenario
GET /api/v1/me HTTP/1.1
Host: api.example.com
Authorization: Bearer not-a-real-tokenExample error response
{
"type": "https://errors.example.com/auth-token-invalid",
"title": "Invalid JWT Token",
"status": 401,
"code": "AUTH_TOKEN_INVALID",
"detail": "The bearer token could not be verified.",
"instance": "/api/v1/me",
"traceId": "01JC3S9WQ4ZV6H2K8N0T7A1BQD"
}Related exceptions
- Lexik\Bundle\JWTAuthenticationBundle\Exception\JWTDecodeFailureException
- Lexik\Bundle\JWTAuthenticationBundle\Exception\InvalidTokenException
- Symfony\Component\Security\Core\Exception\AuthenticationException
Related services & controllers
| Unit | Path | Role |
|---|---|---|
| JwtAuthenticationFailureListener | src/Security/Listener/JwtAuthenticationFailureListener.php | Maps lexik_jwt_authentication.on_jwt_invalid onto the error envelope |
| ApiExceptionSubscriber | src/Http/EventSubscriber/ApiExceptionSubscriber.php | Serialises the envelope and attaches traceId |