{"record":{"id":"d46fa01912c1d018","repo":"google/gson","slug":"unexpected-peeked-when-reading-a-jsonelement","errorCode":null,"errorMessage":"Unexpected ${peeked} when reading a JsonElement.","messagePattern":"Unexpected (.+?) when reading a JsonElement\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java","lineNumber":317,"sourceCode":"    try {\n      result = primitive.getAsInt();\n    } catch (NumberFormatException e) {\n      throw numberFormatException(\"Expected an int but was \" + primitive.getAsString(), e);\n    }\n    popStack();\n    if (stackSize > 0) {\n      pathIndices[stackSize - 1]++;\n    }\n    return result;\n  }\n\n  JsonElement nextJsonElement() throws IOException {\n    JsonToken peeked = peek();\n    if (peeked == JsonToken.NAME\n        || peeked == JsonToken.END_ARRAY\n        || peeked == JsonToken.END_OBJECT\n        || peeked == JsonToken.END_DOCUMENT) {\n      throw new IllegalStateException(\"Unexpected \" + peeked + \" when reading a JsonElement.\");\n    }\n    JsonElement element = (JsonElement) peekStack();\n    skipValue();\n    return element;\n  }\n\n  @Override\n  public void close() throws IOException {\n    stack = new Object[] {SENTINEL_CLOSED};\n    stackSize = 1;\n  }\n\n  @Override\n  public void skipValue() throws IOException {\n    JsonToken peeked = peek();\n    switch (peeked) {\n      case NAME:\n        @SuppressWarnings(\"unused\")","sourceCodeStart":299,"sourceCodeEnd":335,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java#L299-L335","documentation":"JsonTreeReader.nextJsonElement (used by JsonElementTypeAdapter when reading from a JsonElement tree) requires the current token to be a value or the start of an array/object. If peek() returns NAME, END_ARRAY, END_OBJECT, or END_DOCUMENT, it throws IllegalStateException. This signals the read was attempted at a position where no complete element can be produced.","triggerScenarios":"Calling gson.fromJson(jsonElement, JsonElement.class) or otherwise reading a JsonElement out of a JsonTreeReader positioned at a name token or an end-of-container token. Reproducible by re-reading a tree at the wrong cursor position.","commonSituations":"Reusing a JsonTreeReader past its valid cursor; calling nextJsonElement after hasNext() returned false; integrating JsonElement trees with custom adapters that mis-position the reader.","solutions":["Only read a JsonElement when the reader is positioned at a value or container start (check peek() first).","Create a fresh JsonTreeReader from the JsonElement for each parse rather than reusing.","Avoid mixing manual token consumption with JsonElement extraction on the same reader.","If you need the whole tree, use the JsonElement directly instead of re-reading through a JsonTreeReader."],"exampleFix":"// before: reader already consumed past the value\nval reader = JsonTreeReader(tree)\nreader.beginObject(); reader.nextName()\nJsonElementTypeAdapter.ADAPTER.read(reader) // Unexpected NAME when reading a JsonElement\n\n// after: read element before advancing into object structure\nval reader = JsonTreeReader(tree)\nval el = JsonElementTypeAdapter.ADAPTER.read(reader)","handlingStrategy":"validation","validationCode":"// Position the reader at a value/container before extracting a JsonElement\nJsonToken t = reader.peek();\nif (t == NAME || t == END_ARRAY || t == END_OBJECT || t == END_DOCUMENT) {\n  throw new IllegalStateException(\"Cannot read JsonElement at \" + t);\n}\nJsonElement e = JsonElementTypeAdapter.ADAPTER.read(reader);","typeGuard":null,"tryCatchPattern":"try {\n  reader.nextJsonElement();\n} catch (IllegalStateException e) {\n  if (e.getMessage().startsWith(\"Unexpected \") && e.getMessage().contains(\"when reading a JsonElement\")) {\n    // reader mis-positioned; reset to a fresh JsonTreeReader\n    throw new IllegalStateException(\"Re-read from a new reader\", e);\n  }\n  throw e;\n}","preventionTips":["Create a fresh JsonTreeReader per parse rather than reusing.","Use the JsonElement directly instead of re-reading through a JsonTreeReader.","Check peek() before extracting a JsonElement.","Do not mix manual token consumption with JsonElement extraction."],"tags":["json-tree-reader","json-element","reader-state","internal"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}