FasterXML/jackson-databind · error · IllegalArgumentException
Invalid Object Id definition for
Error message
Invalid Object Id definition for %s: cannot find property with name %s
What it means
Thrown by BeanDeserializerFactory when @JsonIdentityInfo uses ObjectIdGenerators.PropertyGenerator and the named property cannot be found among the bean's settable properties. With a property-based generator, the id must live in an existing, settable property on the bean; if no property matches the configured name, the Object Id definition is invalid.
Solutions
- Ensure a settable property with the configured name exists (field, setter, or creator parameter) on the bean.
- Correct the property= value in @JsonIdentityInfo to match an existing property name.
- If the type is abstract and has no settable properties, note the factory skips this for abstract types (databind#4014); ensure concrete subtypes define the property.
- Switch to a non-property generator (e.g., SequenceGenerator, UUIDGenerator) if you have no natural id property.
Example fix
// before: 'id' property does not exist on the bean
@JsonIdentityInfo(
generator=ObjectIdGenerators.PropertyGenerator.class,
property="id")
class Node { String name; }
// after: add the id property
class Node { @JsonProperty("id") Long id; String name; } Defensive patterns
Strategy: validation
Validate before calling
JsonIdentityInfo ann = type.getAnnotation(JsonIdentityInfo.class);
if (ann != null && ann.generator() == ObjectIdGenerators.PropertyGenerator.class) {
Set<String> names = beanProperties.stream().map(BeanPropertyDefinition::getName).collect(toSet());
if (!names.contains(ann.property())) {
throw new IllegalStateException("@JsonIdentityInfo property '" + ann.property() + "' not found on " + type);
}
} Prevention
- Ensure the @JsonIdentityInfo property= names an existing settable property.
- Update the property= value when renaming the id field.
- For abstract types, ensure concrete subtypes define the id property.
- Prefer UUID/Sequence generators when no natural id property exists.
When it happens
Trigger: Annotating a type with @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id") where no field/setter/creator parameter named 'id' exists on the bean (or it is ignored/not visible).
Common situations: Renaming or removing the id property after adding @JsonIdentityInfo; pointing the property to a getter-only (no setter/field) that is not a creator argument; visibility settings hiding the property; misspelling the property name.
Related errors
- _anySetter already set to non-null
- Duplicate property ' ' for
- Cannot deserialize Class
- Cannot deserialize Proxy class
- Could not resolve Object Id
AI-assisted analysis of FasterXML/jackson-databind@87876ca5c0 (2026-08-11).
Data as JSON: /api/errors/b443e2af3ba3a4bb.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/tools/jackson/databind/deser/BeanDeserializerFactory.java:424
JavaType idType;
SettableBeanProperty idProp;
ObjectIdGenerator<?> gen;
ObjectIdResolver resolver = ctxt.objectIdResolverInstance(beanDescRef.getClassInfo(), objectIdInfo);
// Just one special case: Property-based generator is trickier
if (implClass == ObjectIdGenerators.PropertyGenerator.class) { // most special one, needs extra work
PropertyName propName = objectIdInfo.getPropertyName();
idProp = deserBuilder.findProperty(propName);
if (idProp == null) {
// [databind#4014]: For abstract types (interfaces, abstract classes),
// the builder may not have settable properties (no setter/field).
// Concrete subtype deserializers will set up their own ObjectIdReader,
// so we can safely skip it here for the abstract type.
if (beanDescRef.getType().isAbstract()) {
return;
}
throw new IllegalArgumentException("Invalid Object Id definition for %s: cannot find property with name %s".formatted(
ClassUtil.getTypeDescription(beanDescRef.getType()),
ClassUtil.name(propName)));
}
idType = idProp.getType();
gen = new PropertyBasedObjectIdGenerator(objectIdInfo.getScope());
} else {
JavaType type = ctxt.constructType(implClass);
idType = ctxt.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0];
idProp = null;
gen = ctxt.objectIdGeneratorInstance(beanDescRef.getClassInfo(), objectIdInfo);
}
// also: unlike with value deserializers, let's just resolve one we need here
ValueDeserializer<?> deser = ctxt.findRootValueDeserializer(idType);
deserBuilder.setObjectIdReader(ObjectIdReader.construct(idType,
objectIdInfo.getPropertyName(), gen, deser, idProp, resolver));
}
@SuppressWarnings("unchecked")View on GitHub (pinned to 87876ca5c0)