{"record":{"id":"744d3ef70844116a","repo":"jwtk/jjwt","slug":"unable-to-read-compact-jwt-e-getmessage","errorCode":null,"errorMessage":"Unable to read compact JWT: ${e.getMessage()}","messagePattern":"Unable to read compact JWT: (.+?)","errorType":"validation","errorClass":"io.jsonwebtoken.MalformedJwtException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/JwtTokenizer.java","lineNumber":38,"sourceCode":"import io.jsonwebtoken.lang.Assert;\nimport io.jsonwebtoken.lang.Strings;\n\nimport java.io.IOException;\nimport java.io.Reader;\n\npublic class JwtTokenizer {\n\n    static final char DELIMITER = '.';\n\n    private static final String DELIM_ERR_MSG_PREFIX = \"Invalid compact JWT string: Compact JWSs must contain \" +\n            \"exactly 2 period characters, and compact JWEs must contain exactly 4.  Found: \";\n\n    private static int read(Reader r, char[] buf) {\n        try {\n            return r.read(buf);\n        } catch (IOException e) {\n            String msg = \"Unable to read compact JWT: \" + e.getMessage();\n            throw new MalformedJwtException(msg, e);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T extends TokenizedJwt> T tokenize(Reader reader) {\n\n        Assert.notNull(reader, \"Reader argument cannot be null.\");\n\n        CharSequence protectedHeader = Strings.EMPTY; //Both JWS and JWE\n        CharSequence body = Strings.EMPTY; //JWS payload or JWE Ciphertext\n        CharSequence encryptedKey = Strings.EMPTY; //JWE only\n        CharSequence iv = Strings.EMPTY; //JWE only\n        CharSequence digest = Strings.EMPTY; //JWS Signature or JWE AAD Tag\n\n        int delimiterCount = 0;\n        char[] buf = new char[4096];\n        int len = 0;\n        StringBuilder sb = new StringBuilder(4096);","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/JwtTokenizer.java#L20-L56","documentation":"JwtTokenizer.read wraps any IOException from reading the compact JWT's character stream in a MalformedJwtException with this message. The library treats an I/O failure while reading the token as a malformed-token condition, chaining the original IOException as the cause.","triggerScenarios":"Calling Jwts.parser().parse(...) or parseClaimsJws(...) with a Reader whose underlying source (socket, file, stream) throws IOException mid-read.","commonSituations":"Reading tokens from a network stream that was closed or reset; parsing from a file/stream already consumed or with encoding issues; passing an Reader backed by a failing input source instead of the token String.","solutions":["Pass the compact JWT as a String instead of a Reader to avoid streaming I/O","Check the cause (IOException) to fix the underlying source: reopen the stream, check connectivity, or verify file access","Catch MalformedJwtException (or its IOException cause) and retry once if the source is transient"],"exampleFix":"// before\nparser.parseClaimsJws(new InputStreamReader(socket.getInputStream()));\n// after\nString token = readFully(socket.getInputStream()); // no IOException mid-parse\nparser.parseClaimsJws(token);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    Jws<Claims> jws = parser.parseClaimsJws(token);\n} catch (MalformedJwtException e) {\n    Throwable cause = e.getCause();\n    if (cause instanceof IOException) retryOrReopenStream();\n}","preventionTips":["Prefer passing the JWT String directly rather than streaming via Reader","Ensure stream sources are fully readable and closed properly","Check connectivity/file access when parsing from external sources"],"tags":["jwt","io","malformed-token"],"backgroundTag":"invalid-argument-format","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}