{"record":{"id":"75495bb4fd041a63","repo":"FasterXML/jackson-databind","slug":"trying-to-resolve-a-forward-reference-with-id-i","errorCode":null,"errorMessage":"Trying to resolve a forward reference with id [${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/MapDeserializer.java","lineNumber":1036,"sourceCode":"            throws JacksonException\n        {\n            Iterator<MapReferring> iterator = _accumulator.iterator();\n            // Resolve ordering after resolution of an id. This means either:\n            // 1- adding to the result map in case of the first unresolved id.\n            // 2- merge the content of the resolved id with its previous unresolved id.\n            Map<Object,Object> previous = _result;\n            while (iterator.hasNext()) {\n                MapReferring ref = iterator.next();\n                if (ref.hasId(id)) {\n                    iterator.remove();\n                    previous.put(ref.key, value);\n                    previous.putAll(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 map. Called when the bound item\n         * is rebound (e.g., builder → built object).\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            replaceInMap(_result, oldItem, newItem);\n            // Pending accumulator entries may also hold the old item if a later\n            // forward ref hasn't yet resolved.\n            for (MapReferring ref : _accumulator) {\n                replaceInMap(ref.next, oldItem, newItem);","sourceCodeStart":1018,"sourceCodeEnd":1054,"githubUrl":"https://github.com/FasterXML/jackson-databind/blob/a50c7d2a1d57234ac4adf70dbd88ac90db6436e4/src/main/java/tools/jackson/databind/deser/jdk/MapDeserializer.java#L1018-L1054","documentation":"Thrown by MapDeserializer.MapReferring.resolveForwardReference when an attempt is made to resolve a forward object-id reference inside a map value using an id that was never registered as pending in the map's accumulator. The MapReferringAccumulator (analogous to CollectionReferringAccumulator) tracks unresolved forward references during Map<K,@JsonIdentityInfo-V> deserialization and iterates its pending list; if the id doesn't match any entry, it throws.","triggerScenarios":"Deserializing a Map<K,@JsonIdentityInfo-annotated-V> where JSON contains forward object-id references as map values. The framework attempts to resolve an id that was never registered. Manual resolution with an unknown id. Truncated JSON map missing the referenced object definition.","commonSituations":"JSON objects (maps) with values that reference object ids never defined in the document. Inconsistent @JsonIdentityInfo between the map value type and referencing types. Changing deserialization order or using partial reads. Mixing @JsonIdentityInfo maps with custom map deserializers.","solutions":["Ensure the JSON map contains definitions for all referenced object ids in its values.","Verify @JsonIdentityInfo configuration is consistent on the map value type.","If manually resolving, only use ids from the accumulator's pending reference list.","Check for malformed JSON that might introduce unresolved id references."],"exampleFix":"// before: map value references id 7 never defined\n{\"key\":{\"ref\":7}}\n// after: define id 7\n{\"key\":{\"ref\":7},\"other\":{\"@id\":7,\"name\":\"v\"}}","handlingStrategy":"validation","validationCode":"// Pre-validate JSON map values contain all referenced object ids\nJsonNode tree = mapper.readTree(json);\nSet<Object> defined = extractAllIds(tree);\nSet<Object> referenced = extractAllRefs(tree);\nif (!defined.containsAll(referenced)) {\n    throw new IllegalStateException(\"Unresolved map value ids: \" +\n        Sets.difference(referenced, defined));\n}","typeGuard":null,"tryCatchPattern":"try {\n    mapper.readValue(json, new TypeReference<Map<String,MyType>>() {});\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"wasn't previously seen as unresolved\")) {\n        // JSON map is missing an object id definition — fix the data source\n    }\n}","preventionTips":["Ensure JSON maps contain definitions for all referenced object ids in values.","Keep @JsonIdentityInfo consistent on map value types.","Validate id completeness before deserialization."],"tags":["jackson","deserialization","forward-reference","map","json-identity"],"analyzedSha":"a50c7d2a1d57234ac4adf70dbd88ac90db6436e4","analyzedAt":"2026-08-06T20:31:51.404Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}