{"id":"7212b3ee4c56c966","repo":"google/gson","slug":"couldn-t-write-class","errorCode":null,"errorMessage":"Couldn't write {class}","messagePattern":"Couldn't write (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/JsonElementTypeAdapter.java","lineNumber":168,"sourceCode":"      }\n\n    } else if (value.isJsonArray()) {\n      out.beginArray();\n      for (JsonElement e : value.getAsJsonArray()) {\n        write(out, e);\n      }\n      out.endArray();\n\n    } else if (value.isJsonObject()) {\n      out.beginObject();\n      for (Map.Entry<String, JsonElement> e : value.getAsJsonObject().entrySet()) {\n        out.name(e.getKey());\n        write(out, e.getValue());\n      }\n      out.endObject();\n\n    } else {\n      throw new IllegalArgumentException(\"Couldn't write \" + value.getClass());\n    }\n  }\n}\n","sourceCodeStart":150,"sourceCodeEnd":172,"githubUrl":"https://github.com/google/gson/blob/8b8628c65699bc4421696183c62ae0c1b9b281dc/gson/src/main/java/com/google/gson/internal/bind/JsonElementTypeAdapter.java#L150-L172","documentation":"JsonElementTypeAdapter.write throws IllegalArgumentException('Couldn't write ' + value.getClass()) when the JsonElement passed for serialization is not null/jsonNull, not a primitive, not an array, and not an object. The built-in writer only knows how to emit those four shapes; a user-defined JsonElement subclass falls into the final else branch. The {class} is the unsupported JsonElement subclass.","triggerScenarios":"A user subclasses JsonElement (or JsonObject/JsonArray) and overrides identity in a way that makes isJsonObject()/isJsonArray()/isJsonPrimitive()/isJsonNull() all return false, then passes the instance to Gson.toJson / Streams.write / JsonElementTypeAdapter.write.","commonSituations":"Custom JSON tree types intended to add metadata; defensive subclasses that break instanceof checks; libraries that extend JsonObject to add ordering/typing and forget to keep isJsonObject() true.","solutions":["Avoid subclassing JsonElement; favor composition (hold a JsonObject field) instead of inheritance.","If you must subclass, ensure you do not override isJsonObject()/isJsonArray()/isJsonPrimitive()/isJsonNull() to return false for your type — better, convert to a standard JsonObject before serializing.","Before calling toJson, normalize: JsonObject std = custom.toStandardJsonObject(); gson.toJson(std).","If you control the writer path, register a custom TypeAdapter<JsonElement> that handles your subclass."],"exampleFix":"// before\nclass TaggedObject extends JsonObject { String tag; } // isJsonObject() may still be true, but...\n// if a subclass breaks isJsonObject() -> IllegalArgumentException('Couldn't write ' + class)\n\n// after: compose, don't subclass\nclass TaggedObject { String tag; JsonObject payload = new JsonObject(); }\ngson.toJson(tagged); // serialize the composed JsonObject via its own adapter","handlingStrategy":"type-guard","validationCode":"// Reject unsupported JsonElement subclasses before serializing\nif (!(element instanceof JsonObject) && !(element instanceof JsonArray)\n    && !(element instanceof JsonPrimitive) && !(element instanceof JsonNull)) {\n  throw new IllegalArgumentException(\"Unsupported JsonElement: \" + element.getClass());\n}","typeGuard":"static boolean isWritableJsonElement(JsonElement e) {\n  return e == null || e.isJsonNull() || e.isJsonObject()\n      || e.isJsonArray() || e.isJsonPrimitive();\n}","tryCatchPattern":"try {\n  gson.toJson(element);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Couldn't write \")) {\n    throw new IllegalArgumentException(\"Unsupported JsonElement subclass; convert to JsonObject\", e);\n  }\n  throw e;\n}","preventionTips":["Never subclass JsonElement; compose with a JsonObject field instead.","Validate the element type before serializing when receiving trees from third-party code.","Normalize custom elements to standard JsonObject/JsonArray at the boundary."],"tags":["jsonelement","serialization","subclass","tree"],"analyzedSha":"8b8628c65699bc4421696183c62ae0c1b9b281dc","analyzedAt":"2026-08-04T19:12:22.202Z","schemaVersion":2}