FasterXML/jackson-databind · error · IllegalArgumentException
Trying to resolve a forward reference with id [{}] that wasn
Error message
Trying to resolve a forward reference with id [{}] that wasn't previously seen as unresolved. What it means
Thrown by ObjectIdReferenceProperty.PropertyReferring.handleResolvedForwardReference when attempting to resolve a forward reference by an id that was never registered as pending. The PropertyReferring object (created for properties annotated with @JsonObjectIdReferenceProperty) checks hasId(id) and rejects ids it doesn't recognize. This indicates a mismatch between the ids being resolved and those previously tracked during deserialization.
Source
Thrown at src/main/java/tools/jackson/databind/deser/impl/ObjectIdReferenceProperty.java:135
public final static class PropertyReferring extends Referring {
private final ObjectIdReferenceProperty _parent;
public final Object _pojo;
public PropertyReferring(ObjectIdReferenceProperty parent,
UnresolvedForwardReference ref, Class<?> type, Object ob)
{
super(ref, type);
_parent = parent;
_pojo = ob;
}
@Override
public void handleResolvedForwardReference(DeserializationContext ctxt,
Object id, Object value) throws JacksonException
{
if (!hasId(id)) {
throw new IllegalArgumentException("Trying to resolve a forward reference with id [" + id
+ "] that wasn't previously seen as unresolved.");
}
// [databind#1496]: forward ref resolved, remove from pending set
ctxt.removePendingForwardRef(_pojo);
_parent.set(ctxt, _pojo, value);
}
}
}
View on GitHub (pinned to a50c7d2a1d)
Solutions
- Ensure forward references are resolved in the same order they were encountered during deserialization.
- Verify the @JsonIdentityInfo generator produces ids consistent with what appears in the JSON.
- If resolving manually, only pass ids that were returned by the framework's unresolved reference tracking.
- Check for truncated or malformed JSON that might introduce spurious id references.
Example fix
// before: resolving id "99" that was never seen
roid.handleResolvedForwardReference(ctxt, "99", value);
// after: only resolve ids that were registered
if (roid.hasId(id)) {
roid.handleResolvedForwardReference(ctxt, id, value);
} Defensive patterns
Strategy: validation
Validate before calling
// Before resolving, check hasId
if (referring.hasId(id)) {
referring.handleResolvedForwardReference(ctxt, id, value);
} Type guard
if (roid.hasId(id)) {
roid.handleResolvedForwardReference(ctxt, id, value);
} Try / catch
try {
referring.handleResolvedForwardReference(ctxt, id, value);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("wasn't previously seen")) {
logger.warn("Unknown forward ref id: {}", id);
} else { throw e; }
} Prevention
- Only resolve ids that were previously registered as unresolved.
- Keep @JsonIdentityInfo configuration consistent.
- Validate id completeness before resolution.
When it happens
Trigger: A property using @JsonIdentityReference (or @JsonIdentityInfo on a property) where the resolveForwardReference API is called with an id not previously encountered. Programmatic forward-reference resolution out of order. JSON with object id references whose ids don't match any pending unresolved references.
Common situations: Using @JsonIdentityInfo with a property-level reference where the JSON stream contains ids that were never registered. Mixing manual and automatic forward-reference resolution. Deserialization order changes causing id mismatches after a refactor.
Related errors
- Could not resolve Object Id [{}] (for {}).
- Could not resolve Object Id [{}] -- unresolved forward-refer
- Trying to resolve a forward reference with id [{}] that wasn
- Trying to resolve a forward reference with id [{}] that wasn
- Trying to resolve a forward reference with id [${id}] that w
AI-assisted analysis of FasterXML/jackson-databind@a50c7d2a1d (2026-08-06).
Data as JSON: /api/errors/d67043280bffdf60.
Report an issue: GitHub.