sinelaw/fresh · error
Original file size mismatch: expected
Error message
Original file size mismatch: expected {}, got {} What it means
reconstruct_from_chunks verifies that the current size of the original file equals original_size recorded in the chunked recovery metadata. The chunks are diffs against that exact base, so a different size means the base file changed since the recovery data was captured and reconstruction would produce corrupt content; hence InvalidData rather than NotFound.
Solutions
- Restore the original file to the size/contents recorded in the recovery metadata (e.g. git stash or checkout the matching revision) and retry.
- If the current file is intentionally newer, skip chunk-based reconstruction and recover only the chunk contents manually.
- Log and surface both expected and actual sizes to decide whether to force-recover; do not blindly apply chunks to a changed base.
Example fix
// before
let content = storage.reconstruct_from_chunks(&id, &original)?;
// after
let actual = fs::metadata(&original)?.len();
let expected = storage.recorded_original_size(&id)?;
if actual != expected {
eprintln!("original changed since crash ({expected} -> {actual}); skipping reconstruction");
return Ok(None);
}
let content = storage.reconstruct_from_chunks(&id, &original)?; Defensive patterns
Strategy: validation
Validate before calling
let actual = fs::metadata(original_file)?.len();
let expected = storage.recorded_original_size(id)?;
if actual != expected {
eprintln!("original changed since crash: expected {expected}, got {actual}");
return Ok(None);
} Type guard
fn base_unchanged(storage: &RecoveryStorage, id: &str, original: &Path) -> bool {
match (fs::metadata(original), storage.recorded_original_size(id)) {
(Ok(m), Ok(expected)) => m.len() == expected,
_ => false,
}
} Prevention
- Do not edit or save the original file until crash recovery has been completed
- Record and compare a content hash, not just size, for stronger base verification
- Restore the file to its pre-crash state (VCS) before applying recovery chunks
When it happens
Trigger: reconstruct_from_chunks called when the original file was edited, truncated, saved, replaced, or synchronized (git checkout, rsync) after the recovery session recorded its size.
Common situations: User edits/saves the file after the editor crashed, then runs recovery; CI or sync tools touch the file between crash and recovery; restoring an older file version from VCS before recovering.
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
- (serde_json serialization error)
- Chunk content not found
- Chunk file not found
- Chunked recovery data not found
- Metadata file exists but couldn't be read
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/416582872e3a54c2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor/src/services/recovery/storage.rs:486
/// the full modified content.
pub fn reconstruct_from_chunks(&self, id: &str, original_file: &Path) -> io::Result<Vec<u8>> {
let chunked_data = self.read_chunked_content(id)?.ok_or_else(|| {
io::Error::new(io::ErrorKind::NotFound, "Chunked recovery data not found")
})?;
// Read original file
let original_content = fs::read(original_file)?;
tracing::debug!(
"reconstruct_from_chunks: original_file={:?}, file_size_on_disk={}, expected_original_size={}",
original_file,
original_content.len(),
chunked_data.original_size
);
// Verify original file size matches what we expected
if original_content.len() != chunked_data.original_size {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"Original file size mismatch: expected {}, got {}",
chunked_data.original_size,
original_content.len()
),
));
}
// Apply chunks to reconstruct content
let mut result = Vec::with_capacity(chunked_data.final_size);
let mut original_pos = 0;
for chunk in &chunked_data.chunks {
// Copy unchanged content before this chunk
if chunk.offset > original_pos {
result.extend_from_slice(&original_content[original_pos..chunk.offset]);
}View on GitHub (pinned to 67894ca546)