astrid-runtime/astrid · error · std::io::Error::InvalidData

stopped Astrid durable root cannot provision runtime…

Error message

stopped Astrid durable root cannot provision runtime identity sidecars

What it means

Thrown by validate_runtime_identity_provisioning when validate_fresh_root_entries reports the root is in the StoppedVolume state — a detached/stopped durable-volume representation that cannot safely hold runtime identity sidecars (private keys).

Solutions

  1. Start/attach the durable volume that backs the Astrid root, then retry
  2. Run the provisioning/signing operation on the host where the volume is active
  3. Move ASTRID_HOME to a live local directory if volume-backed provisioning is not intended

Example fix

// before: volume stopped
./sign-archive --home /mnt/volume/.astrid  # fails
// after
volume start astrid-durable
./sign-archive --home /mnt/volume/.astrid
Defensive patterns

Strategy: validation

Validate before calling

if !volume_is_active(astrid_home) {
    eprintln!("start/attach the durable volume before provisioning identity");
    return;
}

Try / catch

match dirs.validate_runtime_identity_provisioning() {
    Err(e) if e.to_string().contains("stopped Astrid durable root") => {
        volume_start(); // then retry
    },
    other => other?,
}

Prevention

When it happens

Trigger: Calling validate_runtime_identity_provisioning (via prepare or sign_archive_with_runtime_key_in_home) when the durable root is the stopped volume-only representation, after validate_private_directory succeeds.

Common situations: Attempting to sign or provision keys while the backing durable volume is unmounted/stopped, e.g. running the signing flow on a machine or container where the volume was detached.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/15ffecfb12863fe8. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-core/src/dirs.rs:464

        match std::fs::symlink_metadata(self.root()) {
            Ok(metadata) if metadata.file_type().is_symlink() || !metadata.is_dir() => {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidData,
                    format!(
                        "Astrid home without a layout sentinel is redirected or not a directory: {}",
                        self.root().display()
                    ),
                ));
            },
            Ok(_) => {},
            Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(()),
            Err(error) => return Err(error),
        }
        crate::platform_fs::validate_private_directory(self.root())?;

        if self.validate_fresh_root_entries()? == UnsentinelledRootState::StoppedVolume {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "stopped Astrid durable root cannot provision runtime identity sidecars",
            ));
        }
        Ok(())
    }

    fn validate_fresh_root_entries(&self) -> io::Result<UnsentinelledRootState> {
        let mut entries = self.root().read_dir()?.collect::<Result<Vec<_>, _>>()?;
        entries.sort_by_key(std::fs::DirEntry::file_name);
        if entries.len() == 1 && entries[0].file_name() == std::ffi::OsStr::new("keys") {
            self.validate_runtime_key_bootstrap(&entries[0].path())?;
            return Ok(UnsentinelledRootState::RuntimeKeyBootstrap);
        }
        let mut state = UnsentinelledRootState::Empty;
        for entry in entries {
            let path = entry.path();
            if entry.file_name() != std::ffi::OsStr::new("astrid.volume") {

View on GitHub (pinned to affd8760f4)