{"record":{"id":"e776666c6020f4dc","repo":"gitbutlerapp/gitbutler","slug":"the-model-returned-a-resolution-for-which-wa","errorCode":null,"errorMessage":"The model returned a resolution for \"{}\", which was not requested","messagePattern":"The model returned a resolution for \"(.+?)\", which was not requested","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-api/src/resolve/mod.rs","lineNumber":619,"sourceCode":"        );\n        attempt()\n    })\n}\n\n/// Check the model response against the request and translate it into\n/// full-coverage picks plus the per-file display payload. Any mismatch fails\n/// validation so the caller can retry the model once before giving up.\nfn validate_ai_response(\n    request: &ResolutionRequest,\n    response: &ResolutionResponse,\n) -> anyhow::Result<(apply::PicksPerFile, Vec<ResolvedFile>)> {\n    let files_by_path = apply::index_files_by_path(request)?;\n    let mut picks: apply::PicksPerFile = vec![BTreeMap::new(); request.files.len()];\n    let mut resolved_files: Vec<Option<ResolvedFile>> = vec![None; request.files.len()];\n\n    for resolution in &response.resolutions {\n        let Some(&index) = files_by_path.get(&apply::normalize_path(&resolution.path)) else {\n            bail!(\n                \"The model returned a resolution for \\\"{}\\\", which was not requested\",\n                resolution.path\n            );\n        };\n        if resolved_files[index].is_some() {\n            bail!(\n                \"The model returned more than one resolution for \\\"{}\\\"\",\n                resolution.path\n            );\n        }\n        let file = &request.files[index];\n        if resolution.hunks.len() != file.hunks.len() {\n            bail!(\n                \"The model returned {} resolved hunks for \\\"{}\\\" but the file has {} conflicts\",\n                resolution.hunks.len(),\n                file.path,\n                file.hunks.len()\n            );","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-api/src/resolve/mod.rs#L601-L637","documentation":"After the LLM call, validate_ai_response() maps every returned resolution path onto the request's conflicted files (via normalize_path). A path that matches no requested conflicted file fails validation - the model answered a question that was not asked. resolve_commit_conflicts_with retries the whole model call once on this failure before giving up.","triggerScenarios":"The model hallucinates or renames a path (absolute vs repo-relative, fixed spelling, an imagined file), or 'helpfully' resolves a manual file that was never part of the request.files list. Also triggered when the model returns the path with different separator or casing that normalize_path does not smooth out.","commonSituations":"Weaker models paraphrasing paths; prompts where merged_text paths tempt the model to add files; strict schemas not enforced by the provider so the model drifts from the requested file set.","solutions":["Let the built-in retry run first - the second attempt often self-corrects","Switch to a stronger model via AI settings (model_or_default) if hallucinated paths recur","Fall back to resolve_commit_conflict_hunks with explicit paths, or edit mode, when full AI resolve keeps failing"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await api.resolveCommitConflictsAi(commitId);\n} catch (err) {\n  if (String(err).includes('which was not requested')) {\n    // one automatic retry already happened inside; one manual retry with the same request is reasonable\n    await api.resolveCommitConflictsAi(commitId);\n  } else throw err;\n}","preventionTips":["Prefer stronger models for AI resolution - path hallucination correlates with model size","If injecting resolutions via resolve_commit_conflicts_with, echo request.files paths verbatim","Fall back to explicit per-hunk resolution after two failed model attempts"],"tags":["ai-resolution","llm-validation","path-mismatch","resolve-api"],"backgroundTag":"llm-response-validation-failed","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}