google/gson · error · InvalidObjectException
Deserialization is unsupported
Error message
Deserialization is unsupported
What it means
LinkedTreeMap.writeReplace() emits a LinkedHashMap so non-Gson consumers can deserialize it; LinkedTreeMap.readObject() throws InvalidObjectException to prevent directly reconstructing the AVL-backed form, which would bypass its DoS defenses and invariants (LinkedTreeMap.java:672). Triggered only by deserialization paths that bypass writeReplace.
Solutions
- Do not serialize LinkedTreeMap directly; rely on writeReplace and deserialize the LinkedHashMap replacement.
- Convert to LinkedHashMap explicitly before writing: oos.writeObject(new LinkedHashMap<>(treeMap)).
- Avoid using Java serialization for Gson-internal containers; use Gson itself to (de)serialize the data as JSON.
Example fix
// before oos.writeObject(linkedTreeMap); // later readObject() may throw // after oos.writeObject(new LinkedHashMap<>(linkedTreeMap));
Defensive patterns
Strategy: validation
Validate before calling
Object toWrite = (obj instanceof LinkedTreeMap) ? new LinkedHashMap<>((LinkedTreeMap<?,?>) obj) : obj;
Type guard
static boolean isLinkedTreeMap(Object o) { return o instanceof com.google.gson.internal.LinkedTreeMap; } Try / catch
try { ois.readObject(); } catch (InvalidObjectException e) { /* stream was tampered; reject */ } Prevention
- Never serialize LinkedTreeMap directly; rely on writeReplace or convert to LinkedHashMap.
- Prefer JSON over Java serialization for Gson-managed structures.
- Do not subclass ObjectInputStream in ways that bypass resolveClass replacement.
When it happens
Trigger: An ObjectInputStream stream whose class descriptor names LinkedTreeMap and reaches readObject, e.g. via a tampered stream or a custom ObjectInputStream that ignores/overrides resolveClass resolution of the replacement.
Common situations: Custom Java-serialization harnesses; cross-process RMI/serialization tests with Gson's internal map; maliciously crafted streams; tests that re-serialize and re-deserialize JsonObject state.
Related errors
- Deserialization is unsupported
- Already wrote a name, expecting a value.
- Dangling name
- is not Comparable
- key == null
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/de5890569147fcd5.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java:675
@Override
public void clear() {
LinkedTreeMap.this.clear();
}
}
/**
* If somebody is unlucky enough to have to serialize one of these, serialize it as a
* LinkedHashMap so that they won't need Gson on the other side to deserialize it. Using
* serialization defeats our DoS defense, so most apps shouldn't use it.
*/
private Object writeReplace() throws ObjectStreamException {
return new LinkedHashMap<>(this);
}
private void readObject(ObjectInputStream in) throws IOException {
// Don't permit directly deserializing this class; writeReplace() should have written a
// replacement
throw new InvalidObjectException("Deserialization is unsupported");
}
}
View on GitHub (pinned to 310ac341f2)