astrid-runtime/astrid · error
capsule source changed while archiving
Error message
capsule source changed while archiving {path} What it means
Raised by append_entry after reading a file into memory for the canonical archive: the byte count read differs from the file length recorded during the earlier directory walk (collect_entries). This detects the source mutating between enumeration and archiving, which would make the tar header size and actual content inconsistent.
Solutions
- Re-run the archive/publish command once no process is modifying the source directory.
- Quiesce build watchers/dev servers or run publish from a clean, immutable build output directory.
- Snapshot the source first (copy to a temp dir, or use the same canonical_capsule_archive output) and publish the snapshot.
Example fix
# before: publishing a live watched directory publish ./dev-capsule # watcher mutates files mid-archive # after: snapshot then publish cp -r ./dev-capsule /tmp/snap && publish /tmp/snap
Defensive patterns
Strategy: retry
Validate before calling
fn source_is_quiet(dir: &Path, quiet_secs: u64) -> bool {
// no file modified within the window -> safe to archive
walkdir(dir).all(|e| {
e.metadata().and_then(|m| m.modified()).map_or(false, |t| {
t.elapsed().map(|d| d.as_secs() > quiet_secs).unwrap_or(true)
})
})
} Try / catch
for attempt in 0..3 {
match publish(...) {
Err(e) if e.to_string().contains("changed while archiving") => { sleep(backoff(attempt)); continue; }
other => { other?; break; }
}
} Prevention
- Stop file watchers/dev servers before publishing
- Publish from an immutable snapshot or clean CI artifact
- Re-run publish after transient races instead of ignoring the error
When it happens
Trigger: canonical_capsule_archive running while a file in the source directory is written, truncated, appended, or deleted/replaced concurrently; metadata.len() from the walk no longer matches the bytes read at append time.
Common situations: A dev server or build watcher regenerating files inside the capsule during publish; an editor with autosave writing while archiving; CI racing between build and publish steps.
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 incomplete capsule authority update exists at
- durable capsule archive contains an unsupported entry
- durable capsule archive contains duplicate path
- headless configuration error state was poisoned
- projected file changed while read
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/347c036d28b32ef0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-capsule-install/src/storage.rs:884
header.set_uid(0);
header.set_gid(0);
header.set_mtime(0);
header.set_mode(if metadata.is_dir() { 0o755 } else { 0o644 });
if metadata.is_dir() {
header.set_entry_type(EntryType::Directory);
header.set_size(0);
header.set_cksum();
builder
.append_data(&mut header, path, io::empty())
.with_context(|| format!("append capsule directory {path}"))?;
} else {
let mut file =
File::open(root.join(relative)).with_context(|| format!("open capsule file {path}"))?;
let mut bytes = Vec::new();
file.read_to_end(&mut bytes)
.with_context(|| format!("read capsule file {path}"))?;
if bytes.len() as u64 != metadata.len() {
bail!("capsule source changed while archiving {path}");
}
header.set_entry_type(EntryType::Regular);
header.set_size(bytes.len() as u64);
header.set_cksum();
builder
.append_data(&mut header, path, Cursor::new(&bytes))
.with_context(|| format!("append capsule file {path}"))?;
// Ensure the source was not swapped while it was read. The archive is
// only authoritative after a caller has separately verified its
// digest/receipt; this check turns a common TOCTOU into a hard error.
let mut second = File::open(root.join(relative))?;
let mut second_bytes = Vec::new();
second.read_to_end(&mut second_bytes)?;
if second_bytes != bytes {
bail!("capsule source changed while archiving {path}");
}
}
Ok(())View on GitHub (pinned to affd8760f4)