{"record":{"id":"42475c4fbe8992cd","repo":"FasterXML/jackson-databind","slug":"trying-to-resolve-a-forward-reference-with-id-42475c","errorCode":null,"errorMessage":"Trying to resolve a forward reference with id [{}] that wasn't previously seen as unresolved.","messagePattern":"Trying to resolve a forward reference with id \\[(.+?)\\] that wasn't previously seen as unresolved\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/tools/jackson/databind/deser/jdk/CollectionDeserializer.java","lineNumber":659,"sourceCode":"        public void resolveForwardReference(DeserializationContext ctxt, Object id, Object value) throws JacksonException\n        {\n            Iterator<CollectionReferring> iterator = _accumulator.iterator();\n            // Resolve ordering after resolution of an id. This mean either:\n            // 1- adding to the result collection in case of the first unresolved id.\n            // 2- merge the content of the resolved id with its previous unresolved id.\n            Collection<Object> previous = _result;\n            while (iterator.hasNext()) {\n                CollectionReferring ref = iterator.next();\n                if (ref.hasId(id)) {\n                    iterator.remove();\n                    previous.add(value);\n                    previous.addAll(ref.next);\n                    return;\n                }\n                previous = ref.next;\n            }\n\n            throw new IllegalArgumentException(\"Trying to resolve a forward reference with id [\" + id\n                    + \"] that wasn't previously seen as unresolved.\");\n        }\n\n        /**\n         * Replace a resolved item in the result collection. Called when the bound\n         * item is rebound (e.g., builder → built object) via\n         * {@link Referring#handleItemRebind}.\n         *\n         * @param oldItem Item to replace (Builder)\n         * @param newItem Item to replace {@code oldItem} with (Built value)\n         *\n         * @since 3.2\n         */\n        public void replaceResolvedItem(Object oldItem, Object newItem) {\n            if (_result instanceof List<?>) {\n                @SuppressWarnings(\"unchecked\")\n                List<Object> list = (List<Object>) _result;\n                for (int i = 0, len = list.size(); i < len; i++) {","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/FasterXML/jackson-databind/blob/a50c7d2a1d57234ac4adf70dbd88ac90db6436e4/src/main/java/tools/jackson/databind/deser/jdk/CollectionDeserializer.java#L641-L677","documentation":"Thrown by CollectionDeserializer.CollectionReferringAccumulator.resolveForwardReference when an attempt is made to resolve a forward reference using an id that does not match any pending CollectionReferring entry in the accumulator. The accumulator tracks unresolved forward references during collection deserialization (for collections containing @JsonIdentityInfo objects) and iterates its internal list to find a match; if none is found, it throws IllegalArgumentException.","triggerScenarios":"Deserializing a Collection<@JsonIdentityInfo-annotated-type> where the JSON contains forward object-id references. The framework attempts to resolve an id that was never registered as pending during collection element deserialization. Manual resolution with an unknown id.","commonSituations":"JSON arrays with object identity references where some ids are never defined in the document. Inconsistent @JsonIdentityInfo configuration between the collection element type and the referencing type. Deserializing a partial or truncated array. Stream-based deserialization where not all elements have been read before resolution is attempted.","solutions":["Ensure the JSON array contains definitions for all referenced object ids.","Verify @JsonIdentityInfo scope and generator are consistent across all types in the collection.","If using manual resolution, collect ids only from the accumulator's pending references.","Check for duplicate ids in the JSON that might confuse the accumulator's ordering logic."],"exampleFix":"// before: array references id 3 which is never defined\n[{\"ref\":3},{\"ref\":3}]\n// after: include definition of id 3\n[{\"@id\":3,\"name\":\"foo\"},{\"ref\":3}]","handlingStrategy":"validation","validationCode":"// Pre-validate JSON contains all object ids referenced in collection values\nJsonNode tree = mapper.readTree(json);\nSet<Object> defined = extractAllIds(tree);\nSet<Object> referenced = extractAllRefs(tree);\nif (!defined.containsAll(referenced)) {\n    throw new IllegalStateException(\"Unresolved collection ids: \" +\n        Sets.difference(referenced, defined));\n}","typeGuard":null,"tryCatchPattern":"try {\n    mapper.readValue(json, new TypeReference<List<MyType>>() {});\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"wasn't previously seen as unresolved\")) {\n        // JSON is missing an object id definition — fix the data source\n    }\n}","preventionTips":["Ensure JSON arrays contain definitions for all referenced object ids.","Keep @JsonIdentityInfo consistent across element types.","Validate id completeness before deserialization."],"tags":["jackson","deserialization","forward-reference","collection","json-identity"],"analyzedSha":"a50c7d2a1d57234ac4adf70dbd88ac90db6436e4","analyzedAt":"2026-08-06T20:31:51.404Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}