astrid-runtime/astrid · error

daemon rejected capsule removal

Error message

daemon rejected capsule removal: {message}

What it means

`dispatch_capsule_remove` sends a removal request to the astrid daemon and expects a success response. When the daemon replies with `KernelResponse::Error(message)`, the CLI surfaces the daemon's rejection message wrapped in this bail instead of proceeding to print "Removed".

Solutions

  1. Read the daemon's message after the colon — it states the actual rejection reason — and address it (fix the capsule name, stop the capsule, etc.).
  2. Verify the capsule exists and is stopped with a list/status command before removing.
  3. Restart the daemon if the capsule is in a stuck state, then retry the removal.

Example fix

// before: removing a running/unknown capsule fails
astrid capsule remove my-capsule
// after: check state first, stop, then remove
astrid capsule list
astrid capsule stop my-capsule
astrid capsule remove my-capsule
Defensive patterns

Strategy: try-catch

Validate before calling

// before removing, confirm the capsule exists and is stopped
let status = daemon_client.status(capsule_name)?;
if !status.exists { return Err(format!("capsule '{capsule_name}' not found").into()); }
if status.running { return Err(format!("stop capsule '{capsule_name}' before removing").into()); }

Type guard

fn is_kernel_success(resp: &astrid_core::kernel_api::KernelResponse) -> bool {
    !matches!(resp, astrid_core::kernel_api::KernelResponse::Error(_))
}

Try / catch

match dispatch_capsule_remove(name) {
    Err(e) if e.to_string().starts_with("daemon rejected capsule removal") => {
        let reason = e.to_string().splitn(2, ": ").nth(1).unwrap_or("unknown");
        eprintln!("removal rejected by daemon: {reason}");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Running a capsule remove command when the daemon cannot perform the removal — e.g. the capsule does not exist, is currently running, or the daemon's kernel refuses the operation — and responds with an Error variant.

Common situations: Removing a typo'd or already-deleted capsule name; attempting to remove a capsule with running processes or open references; daemon-side permission or state problems.

Related errors


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

Appendix: source

Thrown at crates/astrid-cli/src/dispatch.rs:467

        .await?
    {
        astrid_core::kernel_api::KernelResponse::Success(_) => {
            if purge {
                let principal = crate::principal::current();
                let entries =
                    commands::capsule::install_headless::list_env_entries(&principal, &name)?;
                for entry in entries {
                    if matches!(entry.scope, astrid_core::kernel_api::EnvStorageScope::Agent) {
                        commands::capsule::install_headless::delete_env_entry(
                            &principal, &name, &entry.key, entry.kind,
                        )?;
                    }
                }
            }
            eprintln!("Removed '{name}'.");
        },
        astrid_core::kernel_api::KernelResponse::Error(message) => {
            anyhow::bail!("daemon rejected capsule removal: {message}");
        },
        other => anyhow::bail!("unexpected daemon response: {other:?}"),
    }
    Ok(ExitCode::SUCCESS)
}

async fn dispatch_mcp(command: McpCommands) -> Result<ExitCode> {
    if !matches!(command, McpCommands::Gc) {
        commands::daemon::validate_runtime_admission()?;
    }
    match command {
        McpCommands::Serve {
            workspace,
            request_timeout: _,
        } => commands::mcp::serve(None, workspace.as_deref()).await,
        McpCommands::Attach { workspace } => {
            commands::mcp::attach(None, workspace.as_deref()).await
        },

View on GitHub (pinned to affd8760f4)