astrid-runtime/astrid · error
materialized capsule member {relative} differs from durable
Error message
materialized capsule member {relative} differs from durable archive What it means
After confirming the file and directory inventories match, verify_published_materialization reads each expected member byte-for-byte with read_projection_file_nofollow and compares it to the bytes stored in the verified durable package (including Capsule.toml, meta.json, and authority.json). This bail fires when an individual materialized file's contents differ from the durable archive, meaning the on-disk projection has been corrupted, truncated, or tampered with relative to the immutable published package.
Source
Thrown at crates/astrid-kernel/src/capsule_materialization.rs:99
.map(ToOwned::to_owned)
.collect::<Vec<_>>();
expected_directories.extend(archive_directories.iter().cloned());
expected_directories.extend(
archive_directories
.iter()
.map(String::as_str)
.flat_map(authenticated_ancestor_directories),
);
if actual.directories != expected_directories {
anyhow::bail!("materialized capsule directory inventory differs from durable package");
}
for (relative, expected) in &expected_files {
let materialized =
Self::read_projection_file_nofollow(&dir.join(relative)).map_err(|error| {
anyhow::anyhow!("read materialized capsule member {relative}: {error}")
})?;
if materialized != *expected {
anyhow::bail!(
"materialized capsule member {relative} differs from durable archive"
);
}
}
let expansions = manifest
.capabilities
.expansions_from(&verified.authority().approved_capabilities);
if !expansions.is_empty() {
anyhow::bail!("materialized capsule manifest exceeds durable authority approval");
}
Ok(())
}
/// Bind durable activation or authorize the explicit workspace portal.
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
pub(crate) fn capture_bound_materialization(
&self,
dir: &Path,View on GitHub (pinned to affd8760f4)
Solutions
- Trigger repair via repair_published_materialization (or ensure_published_materialization): it removes the divergent tree and re-materializes every member byte-identically from the durable registry snapshot.
- Manually delete the capsule's materialized cache directory and reload so it is rebuilt from the durable package.
- Identify which member differs from the error context ({relative}) and stop editing files inside the materialized cache — always rebuild instead.
- If repairs keep failing, confirm the durable registry entry itself is intact (read_verified_durable_package_for_owner succeeds and its snapshot matches the caller's).
Example fix
// before: patching the divergent file in the cache in place
copy_my_fixed_toml_into(&runtime_dir.join("Capsule.toml"));
// after: rebuild the projection from the immutable snapshot
let manifest = kernel.ensure_published_materialization(
&runtime_dir, &principal, &discovery_manifest, &snapshot,
)?; Defensive patterns
Strategy: try-catch
Validate before calling
// Compare the file you suspect against the durable package before loading
let on_disk = std::fs::read(cache_dir.join("Capsule.toml"))?;
if on_disk != verified.manifest_bytes() {
kernel.repair_published_materialization(&cache_dir, &principal, &manifest, &snapshot)?;
} Type guard
fn projection_matches(path: &Path, expected: &[u8]) -> bool {
std::fs::read(path).map(|b| b == expected).unwrap_or(false)
} Try / catch
if let Err(e) = kernel.load_capsule(&cache_dir, &principal) {
if e.to_string().contains("differs from durable archive") {
std::fs::remove_dir_all(&cache_dir)?;
kernel.ensure_published_materialization(&cache_dir, &principal, &manifest, &snapshot)?;
} else { return Err(e); }
} Prevention
- Treat the materialized cache as read-only; edit Capsule.toml in the source project and republish instead.
- Always rebuild the projection from the registry snapshot after any suspected corruption.
- Watch for unclean shutdowns/disk-full events and trigger a repair pass afterward.
- Verify the durable registry entry matches the expected snapshot before blaming the cache.
When it happens
Trigger: For some (relative, expected) pair from the verified package's archive entries, read_projection_file_nofollow succeeds but the returned bytes do not equal the expected bytes — e.g. an edited Capsule.toml inside the cache, a truncated data file after a disk-full write, or a file overwritten by a different capsule version's projection.
Common situations: A developer edited Capsule.toml in the materialized directory to test a change; a crash or power loss left a partially written file; two different capsule versions were materialized into the same path; a virus scanner or sync tool modified cache contents; an attacker tampered with the projection (this check is the tamper detector).
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
- durable capsule {id} manifest digest differs from authority
- durable capsule {id} content digest differs from authority r
- materialized capsule directory inventory differs from durabl
- opaque capsule asset directories cannot be symlinks: {}
- capsule archive contains duplicate entry '{path}'
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/9dc8cc1b68f0b88b.
Report an issue: GitHub.