FasterXML/jackson-databind · error · UnsupportedOperationException

Should never call `set()` on setterless property ('${getName

Error message

Should never call `set()` on setterless property ('${getName()}')

What it means

SetterlessProperty models a read-only Collection/Map property: deserialization works by calling the getter to obtain the existing collection and then populating it. The set() method is intentionally disabled because there is no setter to invoke; calling it is a programming error (the property was never meant to receive a value directly).

Source

Thrown at src/main/java/tools/jackson/databind/deser/impl/SetterlessProperty.java:149

        // we get JSON null might be compatible. If so, implementation could be changed.
        if (toModify == null) {
            ctxt.reportBadDefinition(getType(), "Problem deserializing 'setterless' property '%s': get method returned null".formatted(
                    getName()));
        }
        _valueDeserializer.deserialize(p, ctxt, toModify);
    }

    @Override
    public Object deserializeSetAndReturn(JsonParser p,
    		DeserializationContext ctxt, Object instance) throws JacksonException
    {
        deserializeAndSet(p, ctxt, instance);
        return instance;
    }

    @Override
    public final void set(DeserializationContext ctxt, Object instance, Object value) {
        throw new UnsupportedOperationException("Should never call `set()` on setterless property ('"+getName()+"')");
    }

    @Override
    public Object setAndReturn(DeserializationContext ctxt, Object instance, Object value)
    {
        set(ctxt, instance, value);
        return instance;
    }
}

View on GitHub (pinned to 87876ca5c0)

Solutions

  1. Expose a setter or field for the property if direct assignment is required.
  2. If populating in place is intended, ensure the deserializer goes through deserializeAndSet (which calls the getter and modifies the returned collection), not set().
  3. Filter out SetterlessProperty instances from generic property-iteration code that calls set().
  4. Add @JsonIgnore to the getter or annotate the field appropriately to avoid the property being treated as settable.

Example fix

// before (framework code)
for (SettableBeanProperty p : props) {
    p.set(ctxt, bean, value); // throws on setterless property
}

// after (skip setterless, or use deserializeAndSet)
for (SettableBeanProperty p : props) {
    if (!(p instanceof SetterlessProperty)) {
        p.set(ctxt, bean, value);
    }
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (p instanceof SetterlessProperty) {
    // do not call set(); use deserializeAndSet or skip
    return;
}

Type guard

static boolean isSettable(SettableBeanProperty p) {
    return !(p instanceof SetterlessProperty);
}

Try / catch

try { p.set(ctxt, bean, value); }
catch (UnsupportedOperationException e) {
    if (e.getMessage().contains("setterless property")) {
        // add a setter/field, or skip this property
    } else throw e;
}

Prevention

When it happens

Trigger: Custom code or framework logic that calls SettableBeanProperty.set() on every property indiscriminately, hitting a setterless one; a JSON payload that triggers a code path attempting to assign a new collection to a getter-only field; misuse through reflection.

Common situations: A property exposed only via a getter returning a pre-initialized collection (e.g. private final List<X> items = new ArrayList<>(); with getItems()); code that tries to set rather than modify; using @JsonProperty on a getter-only member with a framework expecting a setter.

Related errors


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