FasterXML/jackson-databind · error · UnresolvedForwardReference

Could not resolve Object Id [{}] -- unresolved forward-refer

Error message

Could not resolve Object Id [{}] -- unresolved forward-reference?

What it means

Thrown as UnresolvedForwardReference during deserialization when an @JsonIdentityInfo object-id reference cannot be matched to a previously-seen object. The id was read, but no object with that id has been registered, so Jackson cannot resolve the pointer.

Source

Thrown at src/main/java/tools/jackson/databind/deser/AbstractDeserializer.java:315

            }
            break;
        }
        return null;
    }

    /**
     * Method called in cases where it looks like we got an Object Id
     * to parse and use as a reference.
     */
    protected Object _deserializeFromObjectId(JsonParser p, DeserializationContext ctxt)
        throws JacksonException
    {
        Object id = _objectIdReader.readObjectReference(p, ctxt);
        ReadableObjectId roid = ctxt.findObjectId(id, _objectIdReader.generator, _objectIdReader.resolver);
        // do we have it resolved?
        Object pojo = roid.resolve();
        if (pojo == null) { // not yet; should wait...
            throw new UnresolvedForwardReference(p,
                    "Could not resolve Object Id ["+id+"] -- unresolved forward-reference?",
                    p.currentLocation(), roid);
        }
        return pojo;
    }
}

View on GitHub (pinned to a50c7d2a1d)

Solutions

  1. Ensure every referenced id is present in the payload and (for streaming) that object definitions appear before references, or deserialize the whole document at once so Jackson can buffer forward references.
  2. For JPA cycles, break the cycle at serialization time (@JsonIgnore on one side) or map to flat DTOs.
  3. Register a DeserializationProblemHandler (handleMissingId) to tolerate missing ids, or use ObjectReader.withHandler.
  4. Catch UnresolvedForwardReference at the boundary and report which id failed.

Example fix

// before: deserialization throws UnresolvedForwardReference on a missing @id
Graph g = mapper.readValue(json, Graph.class);
// after: tolerate unresolved ids via a problem handler
ObjectReader r = mapper.readerFor(Graph.class)
    .withHandler(new DeserializationProblemHandler() {
        @Override public Object handleMissingId(DeserializationContext ctxt, Object referenced) {
            return null; // skip the dangling reference
        }
    });
Graph g = r.readValue(json);
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate that every object-id reference has a matching definition in the payload
Set<Object> defined = collectDefinedIds(jsonNode);     // objects carrying @id
Set<Object> referenced = collectReferencedIds(jsonNode); // pointers to those ids
if (!defined.containsAll(referenced)) {
    throw new IllegalArgumentException("JSON references undefined object ids: "
        + Sets.difference(referenced, defined));
}

Try / catch

try {
    return mapper.readValue(json, Graph.class);
} catch (UnresolvedForwardReference e) {
    log.warn("Unresolved object id while deserializing; payload may be incomplete", e);
    throw new DomainException("Referenced entity not found in payload", e);
}

Prevention

When it happens

Trigger: JSON using @JsonIdentityInfo where an object references an id that never appears, appears after the reference in a non-bufferable stream, or where ids are duplicated/inconsistent. Common with bidirectional JPA entity graphs serialized with identity info.

Common situations: Cyclic JPA entity graphs whose back-reference points to an id that was elided or never serialized; hand-edited/partial JSON snapshots missing an object; id-generator mismatch between serialization and deserialization; streaming reads that don't buffer the whole document.

Related errors


AI-assisted analysis of FasterXML/jackson-databind@a50c7d2a1d (2026-08-06). Data as JSON: /api/errors/4662d89a82b67a41. Report an issue: GitHub.