{"record":{"id":"d811eae517dbb813","repo":"Hmbown/CodeWhale","slug":"the-file-changed-after-the-selected-change-record-refresh","errorCode":null,"errorMessage":"The file changed after the selected change record. Refresh and review it before restoring; nothing was changed.","messagePattern":"The file changed after the selected change record\\. Refresh and review it before restoring; nothing was changed\\.","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"warning","filePath":"crates/tui/src/snapshot/repo.rs","lineNumber":774,"sourceCode":"    ) -> io::Result<Vec<PathRestoreOutcome>> {\n        self.restore_paths_checked(id, rel_paths, || Ok(()))\n    }\n\n    pub fn restore_file_if_unchanged(\n        &self,\n        id: &SnapshotId,\n        rel: &Path,\n        expected_hash: &str,\n    ) -> io::Result<Vec<PathRestoreOutcome>> {\n        let verify = || {\n            let actual = if self.validate_restore_file(rel)? {\n                let bytes = std::fs::read(self.work_tree.join(rel))?;\n                format!(\"sha256:{}\", crate::hashing::sha256_hex(bytes))\n            } else {\n                \"absent\".to_string()\n            };\n            if actual != expected_hash {\n                return Err(io::Error::new(\n                    io::ErrorKind::WouldBlock,\n                    \"The file changed after the selected change record. Refresh and review it before restoring; nothing was changed.\",\n                ));\n            }\n            Ok(())\n        };\n        verify()?;\n        self.restore_paths_checked(id, &[rel.to_path_buf()], verify)\n    }\n\n    fn restore_paths_checked(\n        &self,\n        id: &SnapshotId,\n        rel_paths: &[PathBuf],\n        preflight: impl FnOnce() -> io::Result<()>,\n    ) -> io::Result<Vec<PathRestoreOutcome>> {\n        if rel_paths.is_empty() {\n            return Ok(Vec::new());","sourceCodeStart":756,"sourceCodeEnd":792,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/snapshot/repo.rs#L756-L792","documentation":"restore_file_if_unchanged (crates/tui/src/snapshot/repo.rs:774) computes the sha256 of the live workspace file (or the literal \"absent\") and compares it to the hash recorded with the selected change record. On mismatch it returns a WouldBlock error and performs no write — a last-writer-wins guard ensuring the user reviews what they are about to overwrite. Nothing is modified when this fires.","triggerScenarios":"Restoring a path whose current file content (or absence) differs from the hash captured when the change record was created — the file was edited, regenerated, or deleted/recreated after the snapshot entry was recorded.","commonSituations":"Editing a file between the snapshot and an /undo-style restore; a build step rewriting the file; running the restore from a different branch/checkout than where the change was made.","solutions":["Refresh the change record / re-open the restore picker so hashes are recomputed against current content.","Review the file's current content; if the local edits should be kept, cancel the restore.","If overwriting is intended, force or re-select the change so the expected hash matches current state, then restore."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"fn hash_matches(ws: &Path, rel: &Path, expected: &str) -> std::io::Result<bool> {\n    let actual = match std::fs::read(ws.join(rel)) {\n        Ok(bytes) => format!(\"sha256:{}\", sha256_hex(bytes)),\n        Err(_) => \"absent\".to_string(),\n    };\n    Ok(actual == expected)\n}","typeGuard":null,"tryCatchPattern":"match restore_result {\n    Err(e) if e.kind() == io::ErrorKind::WouldBlock => {\n        // file changed since the change record: refresh picker, re-review\n    }\n    other => other?,\n}","preventionTips":["Restore promptly after selecting a change; avoid editing in between.","Refresh the change record if the workspace was modified since selection.","Treat this error as a safety signal — review content before forcing a restore."],"tags":["restore","conflict","hash-check"],"backgroundTag":"checksum-mismatch","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}