astrid-runtime/astrid · error
materialize durable capsule package
Error message
materialize durable capsule package: {error:#} What it means
Thrown when the actual materialization step — `astrid_capsule_install::materialize_capsule_package(snapshot.package(), target)` — fails after the stale directory was cleared. The package contents from the storage snapshot could not be written into the target directory, and the full error chain (`{error:#}`) is preserved. This is the core 'unpack/install of the capsule package failed' error of the repair path.
Solutions
- Read the inner error chain (`{error:#}` in the message) to identify the root cause (permissions vs disk space vs corrupt package), then fix that specifically.
- Free disk space / raise the quota on the volume holding the materialization target and retry.
- If the stored package is corrupted, re-publish or re-fetch the capsule package snapshot so the storage layer holds valid data.
- Ensure the parent directory of the target exists and is writable by the current user before invoking the operation.
- Serialize concurrent invocations (locks) or use distinct target directories to avoid two processes materializing into the same path.
Example fix
// before: cache dir on a tiny tmpfs export ASTRID_CACHE=/tmp/astrid-cache // after: point the materialization target at persistent writable storage export ASTRID_CACHE=$HOME/.cache/astrid
Defensive patterns
Strategy: try-catch
Validate before calling
use std::path::Path;
fn precheck_materialization(target: &Path) -> Result<(), String> {
let parent = target.parent().ok_or("target has no parent")?;
std::fs::create_dir_all(parent).map_err(|e| format!("parent not creatable: {e}"))?;
let probe = parent.join(".astrid-write-probe");
std::fs::File::create(&probe)
.and_then(|_| std::fs::remove_file(&probe))
.map_err(|e| format!("cache volume not writable: {e}"))?;
let free = fs4_free_space(parent).unwrap_or(u64::MAX);
if free < 64 * 1024 * 1024 {
return Err(format!("only {free} bytes free on cache volume"));
}
Ok(())
} Try / catch
match ensure_published_materialization(&target, &principal, &manifest, &snapshot) {
Ok(m) => Ok(m),
Err(e) if e.to_string().contains("materialize durable capsule package") => {
// full chain is preserved via {error:#}
if e.to_string().contains("No space left") {
free_cache_space()?; // then retry once
ensure_published_materialization(&target, &principal, &manifest, &snapshot)
} else if e.to_string().contains("corrupt") || e.to_string().contains("checksum") {
Err(e.context("stored package appears corrupted; re-publish or re-fetch it"))
} else {
Err(e)
}
}
Err(e) => Err(e),
} Prevention
- Monitor free space on the cache volume; materialization fails hard when the disk is full.
- Re-publish/re-fetch package snapshots after interrupted uploads; treat checksum failures as corrupt stored data.
- Serialize materialization per target (lock) so concurrent runs do not race on the same directory.
- Run under a user/sandbox that is allowed to write the cache path; on CI, cache into the workspace, not read-only system paths.
When it happens
Trigger: Any failure inside `materialize_capsule_package`: disk full during extraction, permission denied creating files in the (recreated) target, corrupted or incomplete package snapshot data from the storage layer, or the target becoming unwritable between the delete and the materialize call.
Common situations: Disk quota or no-space-left conditions on the cache volume; concurrent runs of the tool racing to materialize the same target; corrupted capsule package in the storage backend after an interrupted upload; running under a sandbox (CI container) that forbids writing to the cache path; antivirus/EDR blocking rapid file creation.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- inspect capsule materialization
- read materialized capsule authority
- read materialized capsule member
- read materialized capsule metadata
- AlreadyExists
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/d9c9a2a66fb714cf.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/capsule_materialization.rs:204
anyhow::bail!("capsule materialization target is redirected or not a directory");
}
if let Ok(bound_manifest) =
astrid_capsule::discovery::load_manifest(&target.join("Capsule.toml"))
&& self
.verify_published_materialization(target, principal, &bound_manifest, snapshot)
.is_ok()
{
return Ok(bound_manifest);
}
astrid_core::platform_fs::verify_no_redirects(target).map_err(|error| {
anyhow::anyhow!("capsule materialization target is redirected: {error}")
})?;
std::fs::remove_dir_all(target).map_err(|error| {
anyhow::anyhow!("remove stale capsule materialization: {error}")
})?;
}
astrid_capsule_install::materialize_capsule_package(snapshot.package(), target)
.map_err(|error| anyhow::anyhow!("materialize durable capsule package: {error:#}"))?;
let bound_manifest = astrid_capsule::discovery::load_manifest(&target.join("Capsule.toml"))
.map_err(|error| anyhow::anyhow!(error))?;
self.verify_published_materialization(target, principal, &bound_manifest, snapshot)?;
Ok(bound_manifest)
}
/// Recheck the immutable publication after taking activation locks.
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
pub(crate) fn confirm_published_materialization(
&self,
dir: &Path,
principal: &astrid_core::principal::PrincipalId,
manifest: &astrid_capsule_types::manifest::CapsuleManifest,
snapshot: &astrid_storage::CapsulePackageSnapshot,
) -> anyhow::Result<()> {
let current = self.published_capsule_snapshot(principal, manifest)?;
if current.as_ref() != Some(snapshot) {
anyhow::bail!(View on GitHub (pinned to affd8760f4)