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
- Call beginObject() before name(); reserve name() for object contexts only.
- If the enclosing structure must be an array, emit values directly with value()/beginObject() per element instead of name().
- Restructure so the container kind matches the emit pattern: object -> name/value pairs, array -> bare values.
- 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
- Reserve name() for object contexts; arrays take bare values.
- Keep container kind and emit pattern consistent within a serializer.
- Test serializers under both object and array contexts if they are reused.
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
- Expected one JSON element but was {stack}
- Did not expect a name
- Incomplete document
- Unexpected {peeked} when reading a JsonElement.
- String contains non-ASCII characters: {s}{location}
AI-assisted analysis of google/gson@8b8628c656 (2026-08-04).
Data as JSON: /data/errors/150114207e8209e7.json.
Report an issue: GitHub.