google/gson · error · IllegalStateException
Dangling name: {}
Error message
Dangling name: {} What it means
Thrown by JsonWriter.closeScope() (JsonWriter.java:460-462) when deferredName is non-null at the moment of closing a scope. A non-null deferredName means name() was called but no value was written yet; closing the object/array here would emit a name with no value, producing invalid JSON, so the writer rejects it.
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 310ac341f2)
Solutions
- Always write a value (or nullValue()) after name(); if the value should be omitted, do not call name() at all.
- Decide whether to serialize a field before calling name().
- If you started a name you cannot complete, emit nullValue() to keep the JSON valid, or restructure to avoid the dangling name.
- Set serializeNulls consistently if you rely on nullValue() to fill the slot.
Example fix
// before
writer.beginObject();
writer.name("opt");
if (hasOpt) writer.value(v);
writer.endObject(); // dangling name when !hasOpt
// after
writer.beginObject();
if (hasOpt) {
writer.name("opt").value(v);
}
writer.endObject(); Defensive patterns
Strategy: validation
Validate before calling
writer.beginObject();
if (shouldWriteOpt) {
writer.name("opt").value(v);
}
writer.endObject(); Type guard
// Decide before calling name() whether a value will follow.
boolean willEmitValue = (v != null && shouldSerialize);
if (willEmitValue) writer.name("opt").value(v); Try / catch
try {
writer.endObject();
} catch (IllegalStateException e) {
if (e.getMessage().contains("Dangling name")) {
writer.nullValue(); // make JSON valid, then close
writer.endObject();
} else throw e;
} Prevention
- Never call name() unless you are certain a value will follow.
- Decide field inclusion before emitting the name.
- Add tests for conditional-field serialization branches.
When it happens
Trigger: Calling name("x") and then immediately endObject() or endArray() without an intervening value/nullValue call. Also conditional serializers that emit a name and then skip the value on a branch.
Common situations: Conditional field serialization that writes the name before checking whether to skip the value; serializers that emit a name then hit an exception path that closes the object; refactors that move the value write behind a flag.
Related errors
- Already wrote a name, expecting a value.
- Please begin an object before writing a name.
- Nesting problem.
- JsonWriter is closed.
- Numeric values must be finite, but was {}
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/4d98415481e404f8.
Report an issue: GitHub.