astrid-runtime/astrid · error
corpus input changed while its baseline snapshot was capture
Error message
corpus input changed while its baseline snapshot was captured
What it means
`snapshot_file` hashes a file while streaming it and compares the byte count it saw (`snapshot.logical_bytes`) with the size taken before reading (`expected_bytes`). A mismatch means the file was modified concurrently while the baseline snapshot was being captured, so the snapshot is torn/inconsistent and the library aborts.
Source
Thrown at crates/astrid-storage-chunker-evidence/src/corpus.rs:527
}
fn include_walker_entry(recursive: bool, depth: usize, is_directory: bool, name: &str) -> bool {
!recursive || depth != 1 || !is_directory || !EXCLUDED_TOP_LEVEL_DIRECTORIES.contains(&name)
}
fn snapshot_file(path: &Path) -> Result<FileSnapshot> {
let file = File::open(path)
.with_context(|| format!("open corpus input for snapshot {}", path.display()))?;
let expected_bytes = file
.metadata()
.with_context(|| format!("stat corpus input {}", path.display()))?
.len();
let mut reader = HashingReader::new(BufReader::with_capacity(READER_CAPACITY, file));
std::io::copy(&mut reader, &mut std::io::sink())
.with_context(|| format!("snapshot corpus input {}", path.display()))?;
let snapshot = reader.finish();
if snapshot.logical_bytes != expected_bytes {
bail!("corpus input changed while its baseline snapshot was captured");
}
Ok(snapshot)
}
fn validate_label(label: &str) -> Result<()> {
if label.is_empty()
|| !label
.bytes()
.all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'-')
{
bail!("corpus label must contain only lowercase ASCII letters, digits, and hyphens");
}
Ok(())
}
fn validate_relative_git_path(path: &Path) -> Result<()> {
if path.as_os_str().is_empty()
|| path.is_absolute()View on GitHub (pinned to affd8760f4)
Solutions
- Ensure no other process writes to the corpus while the snapshot runs; stop generators/sync daemons first
- Copy the corpus to a stable, read-only location and snapshot the copy
- Re-run the snapshot; if it keeps failing, find the writer with `lsof <path>` or `fuser`
Example fix
// before let snap = snapshot_file(&path, path.metadata()?.len())?; // file still being written // after std::fs::copy(&path, &stable_copy)?; // freeze input first let snap = snapshot_file(&stable_copy, stable_copy.metadata()?.len())?;
Defensive patterns
Strategy: validation
Validate before calling
let before = std::fs::metadata(path)?.len();
snapshot_file(path, before)?;
if std::fs::metadata(path)?.len() != before { /* file changed again; retry */ } Type guard
fn stable_size(path: &Path, probes: usize) -> Option<u64> {
let mut last = std::fs::metadata(path).ok()?.len();
for _ in 0..probes {
std::thread::sleep(std::time::Duration::from_millis(50));
let now = std::fs::metadata(path).ok()?.len();
if now != last { last = now; }
}
Some(last)
} Try / catch
match snapshot_file(&path, expected_len) {
Ok(snap) => snap,
Err(e) if e.to_string().contains("changed while its baseline snapshot") => {
eprintln!("{path:?} is being written; waiting and retrying");
std::thread::sleep(Duration::from_secs(1));
retry_snapshot(&path)?
}
Err(e) => return Err(e),
} Prevention
- Stop dataset generators, log shippers, and sync clients during snapshotting
- Snapshot a frozen copy rather than live files
- Quiesce writes (size stable across two probes) before hashing
When it happens
Trigger: A file is written, truncated, appended, or rotated between the `metadata().len()` read and the completion of the `std::io::copy` hash inside `snapshot_file` (called by `Input::File`, `collect_files`, `validate_current_file`).
Common situations: Corpus files being regenerated by another process during benchmark setup, log files still being appended to, editors/tmp-file swaps (`mv` atomic renames) landing mid-snapshot, or files on actively-changing network shares.
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
- corpus input changed after the baseline snapshot; rerun agai
- workspace capsule manifest changed while it was being read:
- durable capsule package '{id}' disappeared during removal
- an incomplete capsule authority update exists at {}; remove
- capsule {} disappeared during durable contracts scan
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/076789dd7f73beeb.
Report an issue: GitHub.