{"id":"81b88674afae8e44","repo":"google/gson","slug":"class-declaringtype-getname-declares-mul","errorCode":null,"errorMessage":"Class \" + declaringType.getName() + \" declares multiple JSON fields named '\" + duplicateName + \"'; conflict is caused by fields \" + ReflectionHelper.fieldToString(field1) + \" and \" + ReflectionHelper.fieldToString(field2) + \"\\nSee \" + TroubleshootingGuide.createUrl(\"duplicate-fields\")","messagePattern":"Class \" \\+ declaringType\\.getName\\(\\) \\+ \" declares multiple JSON fields named '\" \\+ duplicateName \\+ \"'; conflict is caused by fields \" \\+ ReflectionHelper\\.fieldToString\\(field1\\) \\+ \" and \" \\+ ReflectionHelper\\.fieldToString\\(field2\\) \\+ \"\\\\nSee \" \\+ TroubleshootingGuide\\.createUrl\\(\"duplicate-fields\"\\)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java","lineNumber":307,"sourceCode":"  }\n\n  private static class FieldsData {\n    static final FieldsData EMPTY = new FieldsData(Collections.emptyMap(), Collections.emptyList());\n\n    /** Maps from JSON member name to field */\n    final Map<String, BoundField> deserializedFields;\n\n    final List<BoundField> serializedFields;\n\n    FieldsData(Map<String, BoundField> deserializedFields, List<BoundField> serializedFields) {\n      this.deserializedFields = deserializedFields;\n      this.serializedFields = serializedFields;\n    }\n  }\n\n  private static IllegalArgumentException createDuplicateFieldException(\n      Class<?> declaringType, String duplicateName, Field field1, Field field2) {\n    throw new IllegalArgumentException(\n        \"Class \"\n            + declaringType.getName()\n            + \" declares multiple JSON fields named '\"\n            + duplicateName\n            + \"'; conflict is caused by fields \"\n            + ReflectionHelper.fieldToString(field1)\n            + \" and \"\n            + ReflectionHelper.fieldToString(field2)\n            + \"\\nSee \"\n            + TroubleshootingGuide.createUrl(\"duplicate-fields\"));\n  }\n\n  private FieldsData getBoundFields(\n      Gson context, TypeToken<?> type, Class<?> raw, boolean blockInaccessible, boolean isRecord) {\n    if (raw.isInterface()) {\n      return FieldsData.EMPTY;\n    }\n","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/google/gson/blob/8b8628c65699bc4421696183c62ae0c1b9b281dc/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java#L289-L325","documentation":"Thrown when two fields of the same class (or its inheritance chain) resolve to the same JSON name after applying the FieldNamingStrategy and @SerializedName, so Gson cannot decide which to use. It is an IllegalArgumentException raised eagerly during adapter construction (getBoundFields), with a link to the troubleshooting guide.","triggerScenarios":"A subclass declares a field whose serializedName collides with an inherited field's serializedName; two fields in the same class are aliased to the same name via @SerializedName alternate; a FieldNamingPolicy remaps two distinct Java names to the same JSON name; explicit @SerializedName(\"x\") on both a parent and child field.","commonSituations":"DTO inheritance hierarchies where child redeclares a parent field with the same @SerializedName; misconfigured alternates that point at an existing name; renaming a field while leaving the old @SerializedName on another field; cross-module shared base classes.","solutions":["Rename one of the conflicting fields or change its @SerializedName value to a distinct name.","Mark one of the duplicate fields transient or exclude it with @Expose.","Remove an unnecessary field redeclaration in the subclass.","Adjust @SerializedName alternate arrays so no alias collides with another field's primary or alternate name."],"exampleFix":"// before\nclass Base { @SerializedName(\"id\") String uid; }\nclass Child extends Base { @SerializedName(\"id\") long pk; }\n// Child -> duplicate 'id'\n\n// after\nclass Child extends Base { @SerializedName(\"pk\") long pk; }","handlingStrategy":"validation","validationCode":"// Eagerly scan for duplicate JSON field names using the same naming policy\nSet<String> names = new HashSet<>();\nfor (Class<?> c = Child.class; c != Object.class; c = c.getSuperclass()) {\n  for (Field f : c.getDeclaredFields()) {\n    String n = fieldNamingPolicy.translateName(f); // or @SerializedName value\n    if (!names.add(n)) throw new IllegalStateException(\"Duplicate JSON name: \" + n);\n  }\n}","typeGuard":"null","tryCatchPattern":"try {\n  gson.fromJson(json, Child.class);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"declares multiple JSON fields named\")) {\n    // rename conflicting field and rebuild adapter\n  } else throw e;\n}","preventionTips":["Avoid redeclaring fields in subclasses; use distinct names.","Keep @SerializedName alternates disjoint across the hierarchy.","Run a startup self-test that builds a Gson and serializes every DTO to surface duplicates early.","Prefer composition over inheritance for serialized types."],"tags":["gson","serializedname","duplicate","inheritance","field-naming"],"analyzedSha":"8b8628c65699bc4421696183c62ae0c1b9b281dc","analyzedAt":"2026-08-04T19:12:22.202Z","schemaVersion":2}