{"record":{"id":"0a4d5983db0def5a","repo":"FasterXML/jackson-databind","slug":"cannot-handle-managed-back-reference-type-v","errorCode":null,"errorMessage":"Cannot handle managed/back reference '{}': type: value deserializer of type {} does not support them","messagePattern":"Cannot handle managed/back reference '(.+?)': type: value deserializer of type (.+?) does not support them","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/tools/jackson/databind/ValueDeserializer.java","lineNumber":456,"sourceCode":"     * Default implementation returns null, as support cannot be implemented\n     * generically. Some standard deserializers (most notably\n     * {@link tools.jackson.databind.deser.bean.BeanDeserializer})\n     * do implement this feature, and may return reader instance, depending on exact\n     * configuration of instance (which is based on type, and referring property).\n     *\n     * @return ObjectIdReader used for resolving possible Object Identifier\n     *    value, instead of full value serialization, if deserializer can do that;\n     *    null if no Object Id is expected.\n     */\n    public ObjectIdReader getObjectIdReader(DeserializationContext ctxt) { return null; }\n\n    /**\n     * Method needed by {@link BeanDeserializerFactory} to properly link\n     * managed- and back-reference pairs.\n     */\n    public SettableBeanProperty findBackReference(String refName)\n    {\n        throw new IllegalArgumentException(\"Cannot handle managed/back reference '\"+refName\n                +\"': type: value deserializer of type \"+getClass().getName()+\" does not support them\");\n    }\n\n    /**\n     * Introspection method that may be called to see whether deserializer supports\n     * update of an existing value (aka \"merging\") or not. Return value should either\n     * be {@link Boolean#FALSE} if update is not supported at all (immutable values);\n     * {@link Boolean#TRUE} if update should usually work (regular POJOs, for example),\n     * or <code>null</code> if this is either not known, or may sometimes work.\n     *<p>\n     * Information gathered is typically used to either prevent merging update for\n     * property (either by skipping, if based on global defaults; or by exception during\n     * deserializer construction if explicit attempt made) if {@link Boolean#FALSE}\n     * returned, or inclusion if {@link Boolean#TRUE} is specified. If \"unknown\" case\n     * (<code>null</code> returned) behavior is to exclude property if global defaults\n     * used; or to allow if explicit per-type or property merging is defined.\n     *<p>\n     * Default implementation returns <code>null</code> to allow explicit per-type","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/FasterXML/jackson-databind/blob/a50c7d2a1d57234ac4adf70dbd88ac90db6436e4/src/main/java/tools/jackson/databind/ValueDeserializer.java#L438-L474","documentation":"ValueDeserializer.findBackReference(String) is, by default in the base class, a fail-loud stub: it throws because the base ValueDeserializer does not understand managed/back references (@JsonBackReference/@JsonManagedReference). Only specific deserializers (notably BeanDeserializer) override it to return the matching SettableBeanProperty. If a deserializer that doesn't support references is wired into a bidirectional parent/child relationship, this error surfaces during deserializer construction.","triggerScenarios":"Annotating a field with @JsonManagedReference/@JsonBackReference on a type whose deserializer is a custom ValueDeserializer (not a BeanDeserializer) or a standard non-bean deserializer (collection, map, primitive, enum); using @JsonIdentityInfo or parent/child refs on a type that delegates to a custom deserializer that never implements findBackReference.","commonSituations":"Adding @JsonBackReference to a wrapper/holder type that is deserialized via a custom ValueDeserializer; bidirectional JPA entities where one side is mapped through a custom deserializer; converting a 2.x custom deserializer that extended JsonDeserializer without overriding findBackReference; mixing tree-model or collection deserializers with reference annotations.","solutions":["If the type genuinely needs managed/back references, ensure it is deserialized by a BeanDeserializer (POJO) — don't replace it with a custom ValueDeserializer, or have your custom deserializer extend BeanDeserializer / delegate reference handling.","Override findBackReference in your custom ValueDeserializer to return the appropriate SettableBeanProperty (or wire references manually).","Remove the @JsonManagedReference/@JsonBackReference annotations if the bidirectional linking isn't actually needed for that type, and handle cycles with @JsonIdentityInfo or @JsonIgnore instead.","Split the type so the annotated side is a plain POJO handled by BeanDeserializer and the custom logic lives in a nested type."],"exampleFix":"// before\npublic class Parent {\n    @JsonManagedReference public List<Child> children;\n}\npublic class Child {\n    @JsonBackReference public Parent parent; // Child uses a custom ValueDeserializer -> throws\n}\n// after: let Child be a normal POJO deserialized by BeanDeserializer,\n// or override in your custom ChildDeserializer:\n@Override\npublic SettableBeanProperty findBackReference(String refName) {\n    return _backRefs.get(refName); // populate during construction\n}","handlingStrategy":"type-guard","validationCode":"// Only apply reference annotations to POJO types deserialized by BeanDeserializer\nif (!BeanDeserializer.class.isAssignableFrom(deser.getClass())) {\n    // do not rely on managed/back reference for this type\n}","typeGuard":"boolean supportsBackRefs(ValueDeserializer<?> d) {\n    try {\n        // findBackReference throws by default in the base class\n        return !(d.findBackReference(\"__probe__\") == null && false);\n    } catch (IllegalArgumentException e) {\n        return false;\n    }\n}","tryCatchPattern":"try {\n    return mapper.readValue(json, TypeWithRefs.class);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"does not support them\")) {\n        // remove reference annotations or switch to a BeanDeserializer-backed type\n    }\n    throw e;\n}","preventionTips":["Only use @JsonManagedReference/@JsonBackReference on POJO types handled by BeanDeserializer.","If you write a custom ValueDeserializer for a referenced type, override findBackReference or delegate to a BeanDeserializer.","Prefer @JsonIdentityInfo for bidirectional graphs with custom deserializers.","Unit-test parent/child round-trip for any type with reference annotations."],"tags":["deserialization","managed-reference","custom-deserializer","configuration"],"analyzedSha":"a50c7d2a1d57234ac4adf70dbd88ac90db6436e4","analyzedAt":"2026-08-06T20:31:51.404Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}