google/gson · error · IllegalStateException

Dangling name: " + deferredName

Error message

Dangling name: " + deferredName

What it means

Thrown by JsonWriter.closeScope() when there is a deferred name still pending while trying to close an object or array. A name() call must always be followed by exactly one value (or nested structure) before the scope can be closed; closing with a dangling name would produce invalid JSON.

Source

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

  /** 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;
  }

  /** Returns the value on the top of the stack. */

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Ensure every name() is immediately followed by a value/nullValue/begin* call on all paths.
  2. Decide whether to emit a field (including its name) before calling name(); guard the whole name+value pair together.
  3. If a value may be absent, call nullValue() (when serializeNulls is on) or omit both name and value.
  4. Restructure conditional serialization so the name is only written once the value is determined.

Example fix

// before
writer.name("optional");
if (value != null) {
  writer.value(value);
}
writer.endObject(); // throws if value was null: dangling name

// after
if (value != null) {
  writer.name("optional").value(value);
}
writer.endObject();
Defensive patterns

Strategy: validation

Validate before calling

// Only write name when you can also write the value
if (value != null) {
  writer.name("field").value(value);
}
// never: writer.name("field") then conditionally skip value

Prevention

When it happens

Trigger: Calling writer.name("x") followed directly by endObject() without writing a value, or any code path where name() is called but the subsequent value write is skipped (e.g. behind an if that evaluates false).

Common situations: Conditional field serialization that writes the name unconditionally but skips the value; early returns/exceptions between name() and value(); refactoring that moves name() out of an if but leaves value() inside.

Related errors


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