Error message
Invalid compact JWT string: Compact JWSs must contain exactly 2 period characters, and compact JWEs must contain exactly 4. Found: 0
Also printed as
- io.jsonwebtoken.MalformedJwtException: Invalid compact JWT string: Compact JWSs must contain exactly 2 period characters, and compact JWEs must contain exactly 4. Found: 1
- io.jsonwebtoken.MalformedJwtException: Compact JWT strings may not contain whitespace.
- io.jsonwebtoken.MalformedJwtException: JWT strings must contain exactly 2 period characters. Found: 0
JJWT 0.12+ wording (note the two spaces before "Found"). JJWT 0.11 and earlier said "JWT strings must contain exactly 2 period characters. Found: N". Input containing spaces fails earlier with "Compact JWT strings may not contain whitespace."
JJWT (Java) — io.jsonwebtoken.MalformedJwtException from JwtParser.parse*
What it means
JJWT counted the dots in the input and found neither the 2 of a signed token (JWS) nor the 4 of an encrypted one (JWE). The string is not a compact JWT, so no key or signature was looked at. "Found: 0" typically means an opaque value such as a session ID or API key; a whitespace complaint means the `Bearer` prefix or a line break is still attached.
Why it happens
The value is not a JWT
commonOpaque OAuth tokens, session cookies, API keys, `"null"` or an empty header value. Only strings of base64url segments separated by dots are compact JWTs.
The Authorization header was passed whole
common`Bearer eyJ…` contains a space, which JJWT rejects before counting dots. Strip the scheme first.
Part of the token is missing
occasionalA token cut at a dot (log truncation, size-limited columns, manual copy) leaves one dot ("Found: 1").
How to fix it
- 1.
Extract the token from the header properly
Accept only `Bearer <token>` (case-insensitive scheme) and answer 401 for anything else.
java static String bearerToken(String authorizationHeader) { if (authorizationHeader == null) return null; String[] parts = authorizationHeader.trim().split("\\s+", 2); if (parts.length != 2 || !parts[0].equalsIgnoreCase("Bearer")) return null; return parts[1]; } - 2.
Or let the framework extract it
Spring Security's resource-server support extracts and validates bearer tokens, including the RFC 6750 error responses.
java // Spring Security resource server: the BearerTokenAuthenticationFilter extracts the token for you. @Bean SecurityFilterChain api(HttpSecurity http) throws Exception { return http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2ResourceServer(oauth -> oauth.jwt(Customizer.withDefaults())) .build(); }