FasterXML/jackson-databind · error · IllegalArgumentException
Cannot handle managed/back reference
Error message
Cannot handle managed/back reference '{}': type: value deserializer of type {} does not support them What it means
Thrown by ValueDeserializer.findBackReference() (the default base implementation) when the deserializer does not support managed/back references (@JsonManagedReference / @JsonBackReference) but is asked to resolve one. Only specific deserializers (notably BeanDeserializer) override findBackReference() to actually link reference pairs; the default implementation always throws to signal lack of support.
Solutions
- Ensure @JsonBackReference / @JsonManagedReference are only used on fields whose type is deserialized by a BeanDeserializer (standard POJOs).
- If you have a custom ValueDeserializer that needs to support references, override findBackReference() in it.
- Remove the managed/back reference annotations from fields whose types are not POJOs and handle the relationship manually (e.g., with @JsonIdentityInfo instead).
Example fix
// before
public class Parent {
@JsonManagedReference
public List<String> items; // List deserializer does not support back-references
}
public class Child {
@JsonBackReference
public Parent parent;
}
// after: use @JsonIdentityInfo for non-bean bidirectional refs
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Parent {
public List<String> items;
} Defensive patterns
Strategy: type-guard
Validate before calling
// Before applying @JsonBackReference, verify the target type is a POJO
if (!isBeanType(fieldType)) {
// do not use @JsonBackReference; use @JsonIdentityInfo instead
} Type guard
boolean supportsBackReferences(ValueDeserializer<?> deser) {
try {
deser.findBackReference("__test__");
return true; // should not reach here for default impl
} catch (IllegalArgumentException e) {
return false;
}
} Prevention
- Only use @JsonManagedReference/@JsonBackReference on POJO (bean) fields.
- Use @JsonIdentityInfo for bidirectional references involving collections, maps, or scalars.
- Test parent-child deserialization for every annotated reference pair.
When it happens
Trigger: Annotating a field with @JsonBackReference on a type whose deserializer is not a BeanDeserializer (e.g., a custom ValueDeserializer, a Map deserializer, or a primitive/scalar deserializer). The BeanDeserializerFactory tries to wire the back-reference during deserializer construction and calls findBackReference() on the value deserializer for the referenced property.
Common situations: Using @JsonBackReference on a field whose type is a collection, map, or scalar. Applying JPA-style bidirectional reference annotations on non-bean types. Custom deserializers that don't implement reference handling.
Related errors
- Unsupported container type
- AnnotationIntrospector returned deserializer definition of…
- Cannot update `Map.Entry` values
AI-assisted analysis of FasterXML/jackson-databind@87876ca5c0 (2026-08-11).
Data as JSON: /api/errors/0a4d5983db0def5a.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/tools/jackson/databind/ValueDeserializer.java:456
* Default implementation returns null, as support cannot be implemented
* generically. Some standard deserializers (most notably
* {@link tools.jackson.databind.deser.bean.BeanDeserializer})
* do implement this feature, and may return reader instance, depending on exact
* configuration of instance (which is based on type, and referring property).
*
* @return ObjectIdReader used for resolving possible Object Identifier
* value, instead of full value serialization, if deserializer can do that;
* null if no Object Id is expected.
*/
public ObjectIdReader getObjectIdReader(DeserializationContext ctxt) { return null; }
/**
* Method needed by {@link BeanDeserializerFactory} to properly link
* managed- and back-reference pairs.
*/
public SettableBeanProperty findBackReference(String refName)
{
throw new IllegalArgumentException("Cannot handle managed/back reference '"+refName
+"': type: value deserializer of type "+getClass().getName()+" does not support them");
}
/**
* Introspection method that may be called to see whether deserializer supports
* update of an existing value (aka "merging") or not. Return value should either
* be {@link Boolean#FALSE} if update is not supported at all (immutable values);
* {@link Boolean#TRUE} if update should usually work (regular POJOs, for example),
* or <code>null</code> if this is either not known, or may sometimes work.
*<p>
* Information gathered is typically used to either prevent merging update for
* property (either by skipping, if based on global defaults; or by exception during
* deserializer construction if explicit attempt made) if {@link Boolean#FALSE}
* returned, or inclusion if {@link Boolean#TRUE} is specified. If "unknown" case
* (<code>null</code> returned) behavior is to exclude property if global defaults
* used; or to allow if explicit per-type or property merging is defined.
*<p>
* Default implementation returns <code>null</code> to allow explicit per-typeView on GitHub (pinned to 87876ca5c0)