astrid-runtime/astrid · error

--capsule is required; native default env storage was retire

Error message

--capsule is required; native default env storage was retired

What it means

run_set and run_delete require an explicit --capsule name because the CLI's built-in native default environment secret storage was removed. validate_optional_capsule refuses to proceed when no capsule argument is supplied, and then validates the name via CapsuleId::new. It exists to force migration off the retired default store rather than silently falling back to it.

Source

Thrown at crates/astrid-cli/src/commands/secret.rs:256

    /// Capsule the secret belongs to.
    #[arg(long, value_name = "NAME")]
    pub capsule: Option<String>,
}

/// Top-level dispatcher for `astrid secret`.
pub(crate) async fn run(cmd: SecretCommand) -> Result<ExitCode> {
    match cmd {
        SecretCommand::Set(args) => run_set(&args).await,
        SecretCommand::List(args) => run_list(&args).await,
        SecretCommand::Delete(args) => run_delete(&args).await,
    }
}

fn validate_optional_capsule(capsule: Option<&str>) -> Result<CapsuleId> {
    CapsuleId::new(
        capsule
            .ok_or_else(|| {
                anyhow::anyhow!("--capsule is required; native default env storage was retired")
            })?
            .to_owned(),
    )
    .context("invalid capsule name")
}

/// Resolve one capsule's non-secret schema through the authenticated daemon
/// inventory. The CLI must not inspect a materialized `Capsule.toml` under a
/// principal home: the registry snapshot is the authority for installed
/// capsule metadata, while workspace capsules are only visible through the
/// explicit workspace inventory.
async fn capsule_env_kind(capsule: &CapsuleId, key: &str) -> Result<Option<EnvValueKind>> {
    let mut client = crate::socket_client::connect_kernel_for_workspace(None).await?;
    let response = client.request(KernelRequest::GetCapsuleMetadata).await?;
    let entries = match response {
        astrid_core::kernel_api::KernelResponse::CapsuleMetadata(entries) => entries,
        astrid_core::kernel_api::KernelResponse::Error(error) => {
            anyhow::bail!("daemon metadata lookup failed: {error}");

View on GitHub (pinned to affd8760f4)

Solutions

  1. Re-run the command passing --capsule <name> with the target capsule.
  2. List existing capsules to find the correct name, then retry with it.
  3. If the secret lived in the retired native default env storage, migrate it into a named capsule first.
  4. Update scripts/CI to always pass --capsule.

Example fix

// before
astrid secret set API_KEY=...
// after
astrid secret set API_KEY=... --capsule prod
Defensive patterns

Strategy: validation

Validate before calling

// shell check before invoking
if [ -z "$CAPSULE" ]; then echo "--capsule is required" >&2; exit 2; fi
// rust: if building args programmatically
assert!(!capsule.is_empty(), "--capsule is required");

Prevention

When it happens

Trigger: Calling `astrid secret set` or `astrid secret delete` without passing --capsule (capsule is None). Also triggered when the value passed to --capsule fails CapsuleId::new validation, though that produces the wrapped 'invalid capsule name' context.

Common situations: Scripts or muscle-memory invocations written before the native default env storage was retired; CI pipelines that relied on an implicit default environment; docs or READMEs still showing the old flagless usage.

Understand the failure class

Background: "--flag is required" and "must specify" CLI errors: how missing-required-flag validation works and how to fix it — this error's family across 20 libraries.

Related errors


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