{"record":{"id":"ed06118c8bedc049","repo":"ultraworkers/claw-code","slug":"old-string-not-found-in-file","errorCode":null,"errorMessage":"old_string not found in file","messagePattern":"old_string not found in file","errorType":"validation","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"rust/crates/runtime/src/file_ops.rs","lineNumber":283,"sourceCode":"}\n\n/// Performs an in-file string replacement and returns patch metadata.\npub fn edit_file(\n    path: &str,\n    old_string: &str,\n    new_string: &str,\n    replace_all: bool,\n) -> io::Result<EditFileOutput> {\n    let absolute_path = normalize_path(path)?;\n    let original_file = fs::read_to_string(&absolute_path)?;\n    if old_string == new_string {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidInput,\n            \"old_string and new_string must differ\",\n        ));\n    }\n    if !original_file.contains(old_string) {\n        return Err(io::Error::new(\n            io::ErrorKind::NotFound,\n            \"old_string not found in file\",\n        ));\n    }\n\n    let updated = if replace_all {\n        original_file.replace(old_string, new_string)\n    } else {\n        original_file.replacen(old_string, new_string, 1)\n    };\n    fs::write(&absolute_path, &updated)?;\n\n    Ok(EditFileOutput {\n        file_path: absolute_path.to_string_lossy().into_owned(),\n        old_string: old_string.to_owned(),\n        new_string: new_string.to_owned(),\n        original_file: original_file.clone(),\n        structured_patch: make_patch(&original_file, &updated),","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/ultraworkers/claw-code/blob/08106b0c3771ef5b4a5aa176acccd460e88b7325/rust/crates/runtime/src/file_ops.rs#L265-L301","documentation":"`edit_file` (runtime/src/file_ops.rs:283) requires the file's current contents to contain `old_string` as an exact byte substring (no whitespace normalization) and returns `ErrorKind::NotFound` otherwise. Note this port has NO multiple-match ambiguity error: without `replace_all` it replaces the FIRST occurrence via `replacen(.., 1)`.","triggerScenarios":"The file changed between the read that produced old_string and the edit (stale buffer); tabs vs spaces; trailing whitespace or line-ending differences; copied old_string from rendered output that collapsed spacing; wrong file path (edited a different copy).","commonSituations":"Concurrent formatters/linters rewriting the file mid-session; agent editing from an outdated file snapshot; CRLF files edited with LF-anchored strings; monorepo duplicate paths.","solutions":["Re-read the file now and copy old_string verbatim from the fresh content.","Widen old_string with surrounding unique context lines so it matches exactly.","Pre-check with the same substring test before calling, and re-verify tabs/CRLF with `cat -A file | head`."],"exampleFix":"# before (stale copy: file changed since read)\nEdit(file=\"src/lib.rs\", old_string=\"fn main() {\\n    println!(\\\"hi\\\")\", ...)\n\n# after (re-read, then anchor on current exact bytes)\nRead(file=\"src/lib.rs\")\nEdit(file=\"src/lib.rs\", old_string=\"fn main() {\\n    println!(\\\"hello\\\")\", ...)","handlingStrategy":"validation","validationCode":"let current = std::fs::read_to_string(path)?;\nif !current.contains(old_string) {\n    // re-copy old_string from `current` (exact bytes, no normalization) before editing\n}","typeGuard":null,"tryCatchPattern":"match edit_file(path, old, new, replace_all) {\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound\n        && e.to_string().contains(\"old_string not found\") => { /* re-read file, rebuild old_string from fresh bytes */ }\n    other => other,\n}","preventionTips":["Always re-read the file immediately before editing; stale snapshots are the top cause","Copy old_string verbatim including tabs/trailing spaces/CRLF","Anchor with surrounding context lines to make matches unambiguous","This port replaces the FIRST match by default — use replace_all only when intended"],"tags":["file-ops","edit","not-found"],"backgroundTag":"search-text-not-found","analyzedSha":"08106b0c3771ef5b4a5aa176acccd460e88b7325","analyzedAt":"2026-08-18T00:29:38.590Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}