{"record":{"id":"99fadb8bbcc7c3e0","repo":"Hmbown/CodeWhale","slug":"patch-context-not-found-in","errorCode":null,"errorMessage":"patch context not found in {}: {}","messagePattern":"patch context not found in (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/eval.rs","lineNumber":720,"sourceCode":"        }\n        if raw_line.starts_with(\"*** \") {\n            return Err(anyhow!(\"unexpected patch directive: {raw_line}\"));\n        }\n        if raw_line.starts_with(\"@@\") {\n            continue;\n        }\n\n        let (kind, rest) = raw_line.split_at(1);\n        let content = rest.to_string();\n\n        match kind {\n            \" \" => {\n                let Some(found) = file_lines[cursor..]\n                    .iter()\n                    .position(|line| line == &content)\n                    .map(|offset| cursor + offset)\n                else {\n                    return Err(anyhow!(\n                        \"patch context not found in {}: {}\",\n                        file_path.display(),\n                        content\n                    ));\n                };\n                cursor = found + 1;\n            }\n            \"-\" => {\n                if cursor >= file_lines.len() || file_lines[cursor] != content {\n                    return Err(anyhow!(\n                        \"patch removal mismatch in {}: expected '{}'\",\n                        file_path.display(),\n                        content\n                    ));\n                }\n                file_lines.remove(cursor);\n            }\n            \"+\" => {","sourceCodeStart":702,"sourceCodeEnd":738,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/eval.rs#L702-L738","documentation":"A context line (leading space) must match some line of the target file at or after the current cursor (eval.rs:720). When no such line exists the patch is stale for the current file content and is rejected with the file path and the unmatched line, before any write.","triggerScenarios":"The file changed since the patch was generated (another patch or hand edit landed first); the context line's whitespace differs (CRLF, trailing spaces); the patch was built against a different version of the file; earlier hunks advanced the cursor past the context.","commonSituations":"Concurrent edits to the same file; model hallucinates file content; line-ending conversion between environments.","solutions":["Re-read the current file and regenerate the patch from its actual lines","Apply patches strictly one at a time, re-reading the file between attempts","Normalize line endings and preserve exact whitespace in context lines"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"let original = std::fs::read_to_string(&file_path)?;\nfor ctx in patch_context_lines(&patch) {\n    anyhow::ensure!(\n        original.lines().any(|l| l == ctx),\n        \"context not present in current file: {ctx}\"\n    );\n}","typeGuard":null,"tryCatchPattern":"let mut attempt = patch.clone();\nloop {\n    match apply_patch(&root, &attempt) {\n        Ok(()) => break,\n        Err(err) if err.to_string().contains(\"patch context not found\") => {\n            attempt = regenerate_patch_against_current_file(&file_path, &edit)?;\n        }\n        Err(err) => return Err(err),\n    }\n}","preventionTips":["Serialize patches to a single writer per file; no concurrent edits","Regenerate patches from freshly read content, never from cached reads","Preserve exact whitespace and line endings in context lines"],"tags":["patch","stale-state","eval","filesystem"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}