google/gson · error · IllegalArgumentException

Class ${declaringTypeName} declares multiple JSON fields nam

Error message

Class ${declaringTypeName} declares multiple JSON fields named '${duplicateName}'; conflict is caused by fields ${field1} and ${field2}
See ${url}

What it means

When building a reflective adapter, Gson maps JSON names to fields. If two fields resolve to the same JSON name it cannot disambiguate, so it throws IllegalArgumentException during Gson.create() (before any data is processed). This catches both deserialization-name and serialization-name collisions across the entire class hierarchy.

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 310ac341f2)

Solutions

  1. Annotate one field with @SerializedName to give it a distinct JSON name
  2. Exclude the duplicate field from serialization/deserialization with transient or @Expose
  3. Rename one of the Java fields so the FieldNamingStrategy produces distinct JSON keys

Example fix

// before
class Parent { @SerializedName("name") String fullName; }
class Child extends Parent { @SerializedName("name") String nickName; }
new GsonBuilder().create(); // throws at build time

// after
class Child extends Parent { @SerializedName("nickName") String nickName; }
Defensive patterns

Strategy: validation

Validate before calling

// At app startup, build Gson eagerly to catch duplicate-field errors before processing data
Gson gson;
try {
    gson = new GsonBuilder().create();
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("multiple JSON fields named")) {
        throw new IllegalStateException("Gson field-name collision detected: " + e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A subclass field shadows a parent field with the same name or @SerializedName; two fields with different Java names map to the same JSON key under a FieldNamingStrategy; two @SerializedName annotations specify the same value.

Common situations: Inheritance hierarchies where a child redeclares a parent field; refactoring a field name without checking the naming policy output; bulk-applying @SerializedName aliases that collide.

Related errors


AI-assisted analysis of google/gson@310ac341f2 (2026-08-10). Data as JSON: /api/errors/e4e56a1fee93f340. Report an issue: GitHub.