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

  1. Trim the token before parsing: token.trim() and also remove internal whitespace if the source wrapped lines
  2. Extract the token from a single canonical source (Authorization header bearer value, cookie) rather than free text
  3. 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

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


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)