lcobucci/jwt · error · Lcobucci\JWT\Token\InvalidTokenStructure
The JWT string is missing the Signature part
Error message
The JWT string is missing the Signature part
What it means
Parser::parse() requires the third JWT segment (the Base64Url-encoded signature) to be non-empty. When it is empty, InvalidTokenStructure::missingSignaturePart() is thrown. A JWT shaped 'header.claims.' cannot be verified.
Solutions
- Use the full token exactly as issued — copy all three segments including the final signature
- Reject tokens lacking a signature; this library requires signed tokens
- Catch InvalidTokenStructure and return 'malformed token' to the client
- If you need unsecured JWTs, use a different mechanism — lcobucci/jwt requires verification of the signature segment
Example fix
// before
$token = $parser->parse($jwt); // jwt = 'aaa.bbb.'
// after
$segments = explode('.', $jwt);
if (count($segments) !== 3 || in_array('', $segments, true)) {
throw new InvalidArgumentException('Malformed JWT: missing signature');
}
$token = $parser->parse($jwt); Defensive patterns
Strategy: validation
Validate before calling
$parts = explode('.', $jwt); if (count($parts) !== 3 || $parts[2] === '') { throw new InvalidArgumentException('JWT signature missing'); } Try / catch
try { $token = $parser->parse($jwt); } catch (Lcobucci\JWT\InvalidTokenStructure $e) { return error_401('Malformed token'); } Prevention
- Copy the complete token; signatures are at the end and most often truncated
- Never accept unsigned (alg:none / missing signature) tokens
- Store tokens in fixed-length-safe storage to avoid tail truncation
When it happens
Trigger: Calling parse('header.claims.') or parse('header.claims') combined with a trailing dot — unsigned/truncated tokens; also JLS-style unsecured JWTs (alg:none) that this library does not accept.
Common situations: Tokens cut off when copied (signature is the last part and often truncated); unsigned JWTs issued by non-compliant services; tests using hand-made tokens without a signature.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- The JWT string is missing the Header part
- The JWT string is missing the Claim part
- The JWT string must have two dots
- headers must be an array with non-empty-string keys
- claims must be an array with non-empty-string keys
AI-assisted analysis of lcobucci/jwt@375813049c (2026-09-14).
Data as JSON: /api/errors/6e6057b604496e74.
Report an issue: GitHub.
Appendix: source
Thrown at src/Token/Parser.php:39
public function __construct(private Decoder $decoder)
{
}
public function parse(string $jwt): TokenInterface
{
[$encodedHeaders, $encodedClaims, $encodedSignature] = $this->splitJwt($jwt);
if ($encodedHeaders === '') {
throw InvalidTokenStructure::missingHeaderPart();
}
if ($encodedClaims === '') {
throw InvalidTokenStructure::missingClaimsPart();
}
if ($encodedSignature === '') {
throw InvalidTokenStructure::missingSignaturePart();
}
$header = $this->parseHeader($encodedHeaders);
return new Plain(
new DataSet($header, $encodedHeaders),
new DataSet($this->parseClaims($encodedClaims), $encodedClaims),
$this->parseSignature($encodedSignature),
);
}
/**
* Splits the JWT string into an array
*
* @param non-empty-string $jwt
*
* @return string[]
*View on GitHub (pinned to 375813049c)