Hmbown/CodeWhale · warning · io::Error
The file changed after the selected change record. Refresh…
Error message
The file changed after the selected change record. Refresh and review it before restoring; nothing was changed.
What it means
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.
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.
Defensive patterns
Strategy: try-catch
Validate before calling
fn hash_matches(ws: &Path, rel: &Path, expected: &str) -> std::io::Result<bool> {
let actual = match std::fs::read(ws.join(rel)) {
Ok(bytes) => format!("sha256:{}", sha256_hex(bytes)),
Err(_) => "absent".to_string(),
};
Ok(actual == expected)
} Try / catch
match restore_result {
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
// file changed since the change record: refresh picker, re-review
}
other => other?,
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- An existing Fleet artifact contains different bytes
- AutomationEditorConflict
- bundle contains conflicting or rejected entries
- destination already exists with different content
- Fleet task selects member whose role is , but worker.role…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/d811eae517dbb813.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/snapshot/repo.rs:774
) -> io::Result<Vec<PathRestoreOutcome>> {
self.restore_paths_checked(id, rel_paths, || Ok(()))
}
pub fn restore_file_if_unchanged(
&self,
id: &SnapshotId,
rel: &Path,
expected_hash: &str,
) -> io::Result<Vec<PathRestoreOutcome>> {
let verify = || {
let actual = if self.validate_restore_file(rel)? {
let bytes = std::fs::read(self.work_tree.join(rel))?;
format!("sha256:{}", crate::hashing::sha256_hex(bytes))
} else {
"absent".to_string()
};
if actual != expected_hash {
return Err(io::Error::new(
io::ErrorKind::WouldBlock,
"The file changed after the selected change record. Refresh and review it before restoring; nothing was changed.",
));
}
Ok(())
};
verify()?;
self.restore_paths_checked(id, &[rel.to_path_buf()], verify)
}
fn restore_paths_checked(
&self,
id: &SnapshotId,
rel_paths: &[PathBuf],
preflight: impl FnOnce() -> io::Result<()>,
) -> io::Result<Vec<PathRestoreOutcome>> {
if rel_paths.is_empty() {
return Ok(Vec::new());View on GitHub (pinned to 73e0f67d83)