{"record":{"id":"de5890569147fcd5","repo":"google/gson","slug":"deserialization-is-unsupported-de5890","errorCode":null,"errorMessage":"Deserialization is unsupported","messagePattern":"Deserialization is unsupported","errorType":"exception","errorClass":"InvalidObjectException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java","lineNumber":675,"sourceCode":"    @Override\n    public void clear() {\n      LinkedTreeMap.this.clear();\n    }\n  }\n\n  /**\n   * If somebody is unlucky enough to have to serialize one of these, serialize it as a\n   * LinkedHashMap so that they won't need Gson on the other side to deserialize it. Using\n   * serialization defeats our DoS defense, so most apps shouldn't use it.\n   */\n  private Object writeReplace() throws ObjectStreamException {\n    return new LinkedHashMap<>(this);\n  }\n\n  private void readObject(ObjectInputStream in) throws IOException {\n    // Don't permit directly deserializing this class; writeReplace() should have written a\n    // replacement\n    throw new InvalidObjectException(\"Deserialization is unsupported\");\n  }\n}\n","sourceCodeStart":657,"sourceCodeEnd":678,"githubUrl":"https://github.com/google/gson/blob/310ac341f2f92a454b229bf21f70d2d18b2b6db7/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java#L657-L678","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\noos.writeObject(linkedTreeMap); // later readObject() may throw\n// after\noos.writeObject(new LinkedHashMap<>(linkedTreeMap));","handlingStrategy":"validation","validationCode":"Object toWrite = (obj instanceof LinkedTreeMap) ? new LinkedHashMap<>((LinkedTreeMap<?,?>) obj) : obj;","typeGuard":"static boolean isLinkedTreeMap(Object o) { return o instanceof com.google.gson.internal.LinkedTreeMap; }","tryCatchPattern":"try { ois.readObject(); } catch (InvalidObjectException e) { /* stream was tampered; reject */ }","preventionTips":["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."],"tags":["gson","serialization","java-io","linkedtreemap"],"backgroundTag":null,"analyzedSha":"310ac341f2f92a454b229bf21f70d2d18b2b6db7","analyzedAt":"2026-08-10T02:58:47.455Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}