google/gson · error · IllegalArgumentException

Class " + declaringType.getName() + " declares multiple JSON

Error message

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")

What it means

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.

Source

Thrown at gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java:307

  }

  private static class FieldsData {
    static final FieldsData EMPTY = new FieldsData(Collections.emptyMap(), Collections.emptyList());

    /** Maps from JSON member name to field */
    final Map<String, BoundField> deserializedFields;

    final List<BoundField> serializedFields;

    FieldsData(Map<String, BoundField> deserializedFields, List<BoundField> serializedFields) {
      this.deserializedFields = deserializedFields;
      this.serializedFields = serializedFields;
    }
  }

  private static IllegalArgumentException createDuplicateFieldException(
      Class<?> declaringType, String duplicateName, Field field1, Field field2) {
    throw new IllegalArgumentException(
        "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"));
  }

  private FieldsData getBoundFields(
      Gson context, TypeToken<?> type, Class<?> raw, boolean blockInaccessible, boolean isRecord) {
    if (raw.isInterface()) {
      return FieldsData.EMPTY;
    }

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Rename one of the conflicting fields or change its @SerializedName value to a distinct name.
  2. Mark one of the duplicate fields transient or exclude it with @Expose.
  3. Remove an unnecessary field redeclaration in the subclass.
  4. Adjust @SerializedName alternate arrays so no alias collides with another field's primary or alternate name.

Example fix

// before
class Base { @SerializedName("id") String uid; }
class Child extends Base { @SerializedName("id") long pk; }
// Child -> duplicate 'id'

// after
class Child extends Base { @SerializedName("pk") long pk; }
Defensive patterns

Strategy: validation

Validate before calling

// Eagerly scan for duplicate JSON field names using the same naming policy
Set<String> names = new HashSet<>();
for (Class<?> c = Child.class; c != Object.class; c = c.getSuperclass()) {
  for (Field f : c.getDeclaredFields()) {
    String n = fieldNamingPolicy.translateName(f); // or @SerializedName value
    if (!names.add(n)) throw new IllegalStateException("Duplicate JSON name: " + n);
  }
}

Type guard

null

Try / catch

try {
  gson.fromJson(json, Child.class);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("declares multiple JSON fields named")) {
    // rename conflicting field and rebuild adapter
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of google/gson@8b8628c656 (2026-08-04). Data as JSON: /data/errors/81b88674afae8e44.json. Report an issue: GitHub.