FasterXML/jackson-databind · error · IllegalStateException

Property '${getName()}' already had index (${_propertyIndex}

Error message

Property '${getName()}' already had index (${_propertyIndex}), trying to assign ${index}

What it means

SettableBeanProperty.assignIndex tracks each property's position in the bean's property array; the same property is being assigned two different indices. The method tolerates reassigning the same index, but two distinct indices indicate the same logical property was registered twice with conflicting positions.

Source

Thrown at src/main/java/tools/jackson/databind/deser/SettableBeanProperty.java:335

    public void setObjectIdInfo(ObjectIdInfo objectIdInfo) {
        _objectIdInfo = objectIdInfo;
    }

    public void setViews(Class<?>[] views) {
        if (views == null) {
            _viewMatcher = null;
        } else {
            _viewMatcher = ViewMatcher.construct(views);
        }
    }

    /**
     * Method used to assign index for property.
     */
    public void assignIndex(int index) {
        if (_propertyIndex != -1) {
            if (_propertyIndex != index) {
                throw new IllegalStateException("Property '"+getName()+"' already had index ("+_propertyIndex+"), trying to assign "+index);
            }
        }
        _propertyIndex = index;
    }

    /**
     * Method called to ensure that the mutator has proper access rights to
     * be called, as per configuration. Overridden by implementations that
     * have mutators that require access, fields and setters.
     */
    public void fixAccess(DeserializationConfig config) {
        ;
    }

    public void markAsIgnorable() { }

    public boolean isIgnorable() { return false; }

View on GitHub (pinned to 87876ca5c0)

Solutions

  1. Eliminate duplicate property names in the target type (check @JsonProperty, getters/setters/fields that collapse to one name).
  2. If using mixins, ensure they do not re-introduce a property already present on the target class.
  3. If you maintain a custom BeanDeserializerFactory/Builder, ensure assignIndex is called once per distinct property instance.
  4. Report a bug with a reproducer if this occurs with vanilla POJOs and no custom factories.

Example fix

// before (conflicting aliases)
class Foo {
    @JsonProperty("name") String a;
    @JsonProperty("name") String b; // duplicate logical name
}

// after (distinct names or remove the duplicate)
class Foo {
    String a;
    String b;
}
Defensive patterns

Strategy: validation

Validate before calling

if (prop.getIndex() != -1 && prop.getIndex() != newIndex) {
    throw new IllegalStateException("Refusing conflicting index on " + prop.getName());
}

Type guard

// internal invariant; no user-facing type guard

Try / catch

try { buildDeserializer(type); }
catch (IllegalStateException e) {
    if (e.getMessage().contains("already had index")) {
        // look for duplicate @JsonProperty names on the type
    } else throw e;
}

Prevention

When it happens

Trigger: Two different SettableBeanProperty instances sharing a name being indexed by BeanPropertyMap construction; a custom BeanDeserializerFactory that mutates indices inconsistently; mixins or rename operations that duplicate a property into the same map.

Common situations: Internal Jackson integrity violation usually surfaced by conflicting @JsonProperty aliases or duplicate property names after mixin application; custom deserializer modules that re-add properties; rarely hit by end users — typically indicates a bug in introspection or a custom factory.

Related errors


AI-assisted analysis of FasterXML/jackson-databind@87876ca5c0 (2026-08-11). Data as JSON: /api/errors/fad52eb60dd5a5a2. Report an issue: GitHub.