{"record":{"id":"efe228cb49b3e7d2","repo":"zed-industries/zed","slug":"ref-target-not-found-in-defs-key-ref-str","errorCode":null,"errorMessage":"$ref target not found in {defs_key}: {ref_str}","messagePattern":"\\$ref target not found in (.+?): (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/language_model_core/src/tool_schema.rs","lineNumber":149,"sourceCode":") -> Result<()> {\n    match value {\n        Value::Object(obj) => {\n            if let Some(ref_str) = obj.get(\"$ref\").and_then(|v| v.as_str()) {\n                // Guard against cycles (A -> B -> A, or self-referential\n                // schemas like a Tree node whose children are Trees)\n                if visiting.iter().any(|v| v == ref_str) {\n                    *obj = Map::new();\n                    return Ok(());\n                }\n\n                let (defs_key, name) = parse_ref(ref_str)?;\n                let defs_for_key = match defs_key {\n                    \"$defs\" => defs,\n                    \"definitions\" => legacy_defs,\n                    _ => None,\n                };\n                let Some(def) = defs_for_key.and_then(|defs| defs.get(name)) else {\n                    anyhow::bail!(\"$ref target not found in {defs_key}: {ref_str}\");\n                };\n\n                let ref_owned = ref_str.to_string();\n\n                // Inline the referenced definition into the current object.\n                let mut resolved = def.clone();\n                if let Value::Object(resolved_obj) = &mut resolved {\n                    for (key, val) in obj.iter() {\n                        if key != \"$ref\" {\n                            resolved_obj.insert(key.clone(), val.clone());\n                        }\n                    }\n                }\n                *value = resolved;\n\n                visiting.push(ref_owned);\n                let result = resolve_refs_recursive(value, defs, legacy_defs, visiting);\n                visiting.pop();","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/language_model_core/src/tool_schema.rs#L131-L167","documentation":"When adapting a tool's JSON Schema for an LLM, tool_schema inlines every $ref by looking the name up under the top-level $defs (or legacy definitions) map. If the referenced definition is absent from whichever key the ref parsed into, resolution fails with this error naming the defs key and the full ref string.","triggerScenarios":"A tool input_schema containing \"{$ref\": \"#/$defs/Foo\"} where Foo is missing, defined under definitions while the ref points at $defs (or vice versa), or where a build step stripped the $defs block from the schema before it reached the LLM request.","commonSituations":"Hand-written tool schemas referencing shared types that were never inlined; serde(schemars)-generated schemas where the definition map was flattened/renamed; editing a tool schema and forgetting to move its defs along.","solutions":["Add the missing definition to the same top-level key the ref points at ($defs vs definitions must match exactly)","Run the schema through a $ref bundler (e.g. jsonschema-ref-parser dereference) before passing it to the tool","Inline the referenced object directly and drop the $ref","Validate that the ref name has no typo/case mismatch with the def key"],"exampleFix":"// before\n{\n  \"type\": \"object\",\n  \"properties\": { \"cfg\": { \"$ref\": \"#/$defs/Config\" } }\n}\n\n// after\n{\n  \"type\": \"object\",\n  \"properties\": { \"cfg\": { \"$ref\": \"#/$defs/Config\" } },\n  \"$defs\": {\n    \"Config\": { \"type\": \"object\", \"properties\": { \"name\": { \"type\": \"string\" } } }\n  }\n}","handlingStrategy":"validation","validationCode":"fn refs_resolvable(schema: &serde_json::Value) -> bool {\n    let Some(map) = schema.as_object() else { return true };\n    let defs = map.get(\"$defs\").or_else(|| map.get(\"definitions\"));\n    walk_refs(schema, &|r| {\n        let Ok((key, name)) = parse_ref(r) else { return false };\n        defs.map(|d| d.get(name).is_some() && ((key == \"$defs\") == map.contains_key(\"$defs\"))).unwrap_or(false)\n    })\n}","typeGuard":"fn is_inlineable_ref(ref_str: &str, defs: Option<&serde_json::Map<String, serde_json::Value>>) -> bool {\n    matches!(parse_ref(ref_str), Ok((_, name))) && defs.is_some_and(|d| d.get(name).is_some())\n}","tryCatchPattern":null,"preventionTips":["Validate tool schemas (refs resolve, defs present) at registration time, not at request time","Use schemars/jsonschema tooling to generate self-contained schemas","Keep $defs and the $ref prefix in sync — '#/$defs/X' will not look in 'definitions'"],"tags":["json-schema","json-ref","llm","tools","schema-resolution"],"backgroundTag":"json-schema-unresolved-ref","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}