jwtk/jjwt · error · io.jsonwebtoken.MalformedJwtException
Compact JWT strings may not contain whitespace.
Error message
Compact JWT strings may not contain whitespace.
What it means
Compact JWT serialization (header.payload.signature or 5-part JWE) must be a single whitespace-free string. JwtTokenizer scans every character while tokenizing and throws MalformedJwtException if any whitespace character is present, since whitespace would make the compact form ambiguous and non-standard.
Solutions
- Trim the token before parsing: token.trim() and also remove internal whitespace if the source wrapped lines
- Extract the token from a single canonical source (Authorization header bearer value, cookie) rather than free text
- Catch MalformedJwtException and return a 400-level 'malformed token' response
Example fix
// before
String token = configFileLine; // "eyJ...\n.eyJ..."
Jwts.parser().verifyWith(key).parseClaimsJws(token);
// after
String token = configFileLine.replaceAll("\\s", "");
Jwts.parser().verifyWith(key).parseClaimsJws(token); Defensive patterns
Strategy: validation
Validate before calling
if (token == null || !token.trim().equals(token) || token.chars().anyMatch(Character::isWhitespace)) {
throw new MalformedJwtException("JWT contains whitespace");
} Try / catch
try {
Jws<Claims> jws = parser.parseClaimsJws(token.trim());
} catch (MalformedJwtException e) {
respond(400, "Malformed token");
} Prevention
- Always trim tokens read from files, env vars, or user input
- Extract tokens from structured sources (Authorization header) not pasted text
- Strip line wraps when copying tokens out of logs or documents
When it happens
Trigger: Calling parse/parseClaimsJws with a token String containing spaces, newlines, or tabs — typically from copy-paste, log output wrapping, base64 line breaks, or reading a token from a file/database with trailing '\n'.
Common situations: Tokens pasted from emails/docs/PDFs with line wraps; tokens read from files or environment variables without trimming; tokens embedded in HTML/log text and extracted with surrounding whitespace.
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
- Compact JWE strings MUST always contain a payload…
- Compact JWT strings MUST always have a Base64Url protected…
- Invalid Base64Url
- Invalid compact JWT string: Compact JWSs must contain…
- JWEs do not support key management alg header value 'none'…
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/749caa8b6875af6a.
Report an issue: GitHub.
Appendix: source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/JwtTokenizer.java:67
CharSequence encryptedKey = Strings.EMPTY; //JWE only
CharSequence iv = Strings.EMPTY; //JWE only
CharSequence digest = Strings.EMPTY; //JWS Signature or JWE AAD Tag
int delimiterCount = 0;
char[] buf = new char[4096];
int len = 0;
StringBuilder sb = new StringBuilder(4096);
while (len != Streams.EOF) {
len = read(reader, buf);
for (int i = 0; i < len; i++) {
char c = buf[i];
if (Character.isWhitespace(c)) {
String msg = "Compact JWT strings may not contain whitespace.";
throw new MalformedJwtException(msg);
}
if (c == DELIMITER) {
CharSequence seq = Strings.clean(sb);
String token = seq != null ? seq.toString() : Strings.EMPTY;
switch (delimiterCount) {
case 0:
protectedHeader = token;
break;
case 1:
body = token; //for JWS
encryptedKey = token; //for JWE
break;
case 2:
body = Strings.EMPTY; //clear out value set for JWS
iv = token;View on GitHub (pinned to fb71496164)