google/gson · error · IllegalStateException

Nesting problem.

Error message

Nesting problem.

What it means

Thrown by JsonWriter.closeScope() (used by endArray/endObject) when the current scope on the stack is neither the matching empty nor nonempty scope. This indicates mismatched begin/end calls, e.g. calling endArray() when an object is currently open, or calling endObject() twice.

Source

Thrown at gson/src/main/java/com/google/gson/stream/JsonWriter.java:458

  public JsonWriter endObject() throws IOException {
    return closeScope(EMPTY_OBJECT, NONEMPTY_OBJECT, '}');
  }

  /** Enters a new scope by appending any necessary whitespace and the given bracket. */
  @CanIgnoreReturnValue
  private JsonWriter openScope(int empty, char openBracket) throws IOException {
    beforeValue();
    push(empty);
    out.write(openBracket);
    return this;
  }

  /** Closes the current scope by appending any necessary whitespace and the given bracket. */
  @CanIgnoreReturnValue
  private JsonWriter closeScope(int empty, int nonempty, char closeBracket) throws IOException {
    int context = peek();
    if (context != nonempty && context != empty) {
      throw new IllegalStateException("Nesting problem.");
    }
    if (deferredName != null) {
      throw new IllegalStateException("Dangling name: " + deferredName);
    }

    stackSize--;
    if (context == nonempty) {
      newline();
    }
    out.write(closeBracket);
    return this;
  }

  private void push(int newTop) {
    if (stackSize == stack.length) {
      stack = Arrays.copyOf(stack, stackSize * 2);
    }
    stack[stackSize++] = newTop;

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Audit every beginObject/beginArray to ensure a matching endObject/endArray on every code path (use try-finally).
  2. Build the structure first in memory and serialize, or use Gson's tree model, to avoid manual balancing.
  3. Add unit tests that round-trip the writer output through a JsonReader to catch imbalance.
  4. Use a state-tracking wrapper that asserts begin/end symmetry.

Example fix

// before
writer.beginObject();
if (cond) {
  writer.endArray(); // wrong: should be endObject(), or no end at all
}

// after
writer.beginObject();
try {
  // ... write fields
} finally {
  writer.endObject();
}
Defensive patterns

Strategy: validation

Validate before calling

// Use a wrapper that balances begin/end on every path
JsonWriter w = ...;
w.beginObject();
try {
  // write fields
} finally {
  w.endObject();
}
// or assert symmetry in tests by round-tripping the produced JSON

Prevention

When it happens

Trigger: Calling endArray() after beginObject() (or vice versa), or calling an end method without a corresponding begin, or emitting more end calls than begins. The scope mismatch is detected at JsonWriter.java:457.

Common situations: Branching serialization logic where one path emits an extra end or skips one; manual writer use with conditionals that forget to balance brackets; refactoring tree-building code and losing a begin/end pairing.

Related errors


AI-assisted analysis of google/gson@8b8628c656 (2026-08-04). Data as JSON: /data/errors/a228fe1914c7db9c.json. Report an issue: GitHub.