jwtk/jjwt · error · JSONException

Unable to obtain JSON String from Reader:

Error message

Unable to obtain JSON String from Reader: 

What it means

OrgJsonDeserializer.newTokener wraps an IOException raised while reading the whole JSON string from a Reader into a JSONException with this message. It happens on the fallback path (no JSONTokener(Reader) constructor available, e.g. older org.json or Android) when the reader itself fails mid-read.

Source

Thrown at extensions/orgjson/src/main/java/io/jsonwebtoken/orgjson/io/OrgJsonDeserializer.java:169

            int n = 0;
            while (EOF != n) {
                n = reader.read(buf);
                if (n > 0) sb.append(buf, 0, n);
            }
            return sb.toString();
        }

        private JSONTokener newTokener(Reader reader) {
            if (this.readerCtorAvailable) {
                return new JSONTokener(reader);
            }
            // otherwise not available, likely Android or earlier org.json version, fall back to String ctor:
            String s;
            try {
                s = toString(reader);
            } catch (IOException ex) {
                String msg = "Unable to obtain JSON String from Reader: " + ex.getMessage();
                throw new JSONException(msg, ex);
            }
            return new JSONTokener(s);
        }
    }
}

View on GitHub (pinned to fb71496164)

Solutions

  1. Ensure the underlying stream is open and fully readable before parsing
  2. Read the token source fully into a String yourself with proper IOException handling, then parse the String
  3. Catch JSONException (getCause() instanceof IOException) and handle/retry the read
  4. Use a fresh InputStream per parse — streams cannot be reused after consumption

Example fix

// before
Jwts.parser().build().parse(inputReader); // JSONException wrapping IOException
// after
String jwt = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
Jwts.parser().build().parse(jwt);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!reader.ready()) throw new IllegalStateException("Reader not ready before JSON parse");

Try / catch

try {
    jwt = Jwts.parser().build().parse(readerSource);
} catch (JSONException e) {
    if (e.getCause() instanceof IOException io) throw new UncheckedIOException("Failed reading JWT source", io);
    throw e;
}

Prevention

When it happens

Trigger: Parsing a JWT/JSON from an InputStream/Reader whose underlying stream throws IOException — closed stream, network socket reset, or unreadable source — on platforms lacking the tokener-from-reader constructor.

Common situations: Reading tokens from an HTTP body stream that timed out or was closed early; Android devices with old org.json; reusing already-consumed streams.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/24da921e7b11a52d. Report an issue: GitHub.