google/gson · error · IllegalStateException

Please begin an object before writing a name.

Error message

Please begin an object before writing a name.

What it means

Thrown by JsonTreeWriter.name() when the stack is non-empty, pendingName is null, but the top of the stack is not a JsonObject (it's a JsonArray). name() is only valid inside an object; arrays contain values directly, not name/value pairs.

Source

Thrown at gson/src/main/java/com/google/gson/internal/bind/JsonTreeWriter.java:157

      stack.remove(stack.size() - 1);
      return this;
    }
    throw new IllegalStateException();
  }

  @CanIgnoreReturnValue
  @Override
  public JsonWriter name(String name) throws IOException {
    Objects.requireNonNull(name, "name == null");
    if (stack.isEmpty() || pendingName != null) {
      throw new IllegalStateException("Did not expect a name");
    }
    JsonElement element = peek();
    if (element instanceof JsonObject) {
      pendingName = name;
      return this;
    }
    throw new IllegalStateException("Please begin an object before writing a name.");
  }

  @CanIgnoreReturnValue
  @Override
  public JsonWriter value(String value) throws IOException {
    if (value == null) {
      return nullValue();
    }
    put(new JsonPrimitive(value));
    return this;
  }

  @CanIgnoreReturnValue
  @Override
  public JsonWriter value(boolean value) throws IOException {
    put(new JsonPrimitive(value));
    return this;
  }

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Call beginObject() before name(); reserve name() for object contexts only.
  2. If the enclosing structure must be an array, emit values directly with value()/beginObject() per element instead of name().
  3. Restructure so the container kind matches the emit pattern: object -> name/value pairs, array -> bare values.
  4. Guard name() with a check of the current container kind if your adapter is polymorphic.

Example fix

// before: name() inside an array
out.beginArray();
out.name("x").value(1); // throws: Please begin an object
out.endArray();

// after: either use an object, or emit bare values in the array
out.beginArray();
out.value(1);
out.endArray();
// or, if you want names:
out.beginObject();
out.name("x").value(1);
out.endObject();
Defensive patterns

Strategy: validation

Validate before calling

// Ensure current container is an object before calling name()
if (currentContainer != ContainerKind.OBJECT) throw new IllegalStateException("name() requires an object");
out.name(k);

Try / catch

try {
  out.name(k);
} catch (IllegalStateException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Please begin an object")) {
    // open an object, or emit as a bare value if array was intended
    out.value(v);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling name() while the current open container is an array (top of stack is JsonArray). Typically a serializer that writes fields as name/value but the enclosing structure was opened as beginArray().

Common situations: Serializer that was written for an object output but is being driven inside an array context (e.g. a collection adapter); refactor that changed the root from object to array without removing name() calls; misconfigured custom adapter that emits name() unconditionally.

Related errors


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