{"id":"b066dcbdcf8b1544","repo":"google/gson","slug":"jsonreader-is-closed-b066dc","errorCode":null,"errorMessage":"JsonReader is closed","messagePattern":"JsonReader is closed","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/stream/JsonReader.java","lineNumber":674,"sourceCode":"        default:\n          throw syntaxError(\"Expected ':'\");\n      }\n    } else if (peekStack == JsonScope.EMPTY_DOCUMENT) {\n      if (strictness == Strictness.LENIENT) {\n        consumeNonExecutePrefix();\n      }\n      stack[stackSize - 1] = JsonScope.NONEMPTY_DOCUMENT;\n    } else if (peekStack == JsonScope.NONEMPTY_DOCUMENT) {\n      int c = nextNonWhitespace(false);\n      if (c == -1) {\n        peeked = PEEKED_EOF;\n        return peeked;\n      } else {\n        checkLenient();\n        pos--;\n      }\n    } else if (peekStack == JsonScope.CLOSED) {\n      throw new IllegalStateException(\"JsonReader is closed\");\n    }\n\n    int c = nextNonWhitespace(true);\n    switch (c) {\n      case ']':\n        if (peekStack == JsonScope.EMPTY_ARRAY) {\n          peeked = PEEKED_END_ARRAY;\n          return peeked;\n        }\n      // fall-through to handle \",]\"\n      case ';':\n      case ',':\n        // In lenient mode, a 0-length literal in an array means 'null'.\n        if (peekStack == JsonScope.EMPTY_ARRAY || peekStack == JsonScope.NONEMPTY_ARRAY) {\n          checkLenient();\n          pos--;\n          peeked = PEEKED_NULL;\n          return peeked;","sourceCodeStart":656,"sourceCodeEnd":692,"githubUrl":"https://github.com/google/gson/blob/8b8628c65699bc4421696183c62ae0c1b9b281dc/gson/src/main/java/com/google/gson/stream/JsonReader.java#L656-L692","documentation":"Thrown by JsonReader.doPeek (and any operation that triggers it) once the reader's scope stack top is JsonScope.CLOSED, i.e. after close() has been called. The reader is single-use; continuing to read from it is a programmer error, surfaced as IllegalStateException rather than silently returning stale data.","triggerScenarios":"Calling any of peek(), hasNext(), beginObject(), nextString(), etc. on a JsonReader instance after close() has been invoked (e.g. via try-with-resources that auto-closes, then a later read attempt).","commonSituations":"Storing the JsonReader in a field and closing it in one method while another method still reads; returning a reader from a try-with-resources block; wrapping parsing logic where the cleanup path closes early on an exception but processing continues.","solutions":["Do not use a JsonReader after close(); perform all reads inside the same scope before closing.","Avoid try-with-resources if the reader must outlive the current method; manage its lifecycle explicitly and close exactly once.","If re-parsing is needed, create a fresh JsonReader from the original source.","Guard with a boolean isOpen flag in your wrapper to fail with a clearer message."],"exampleFix":"// before\ntry (JsonReader reader = new JsonReader(new StringReader(json))) {\n  // ...\n}\nreader.peek(); // throws 'JsonReader is closed'\n\n// after\nJsonReader reader = new JsonReader(new StringReader(json));\ntry {\n  // ... all reads here\n} finally {\n  reader.close();\n}","handlingStrategy":"try-catch","validationCode":"// Track closed state in a wrapper\nJsonReader reader = ...;\nboolean closed = false;\n// single source of close():\nvoid closeReader() throws IOException { reader.close(); closed = true; }\n// guard reads:\nvoid safePeek() throws IOException {\n  if (closed) throw new IllegalStateException(\"reader already closed\");\n  reader.peek();\n}","typeGuard":null,"tryCatchPattern":"try {\n  reader.peek();\n} catch (IllegalStateException e) {\n  if (e.getMessage().equals(\"JsonReader is closed\")) {\n    // recreate reader or report upstream; do not silently ignore\n  } else throw e;\n}","preventionTips":["Perform all reads within the lifecycle scope that owns the reader; close exactly once at the end.","Avoid returning a JsonReader from a try-with-resources block.","Keep reader usage in a single method where possible.","Add a closed-flag wrapper if the reader must be shared across methods."],"tags":["gson","jsonreader","lifecycle","resource-management"],"analyzedSha":"8b8628c65699bc4421696183c62ae0c1b9b281dc","analyzedAt":"2026-08-04T19:12:22.202Z","schemaVersion":2}