astrid-runtime/astrid · error

invalid --process-allow entry

Error message

invalid --process-allow entry {entry:?}: {e}

What it means

Raised in build_caps_to_grant when a --process-allow entry fails astrid_core::capability_grammar::validate_capability after being formatted as 'process:spawn:{entry}'. The capability grammar validator rejects binaries or path patterns that are not valid spawn capability tokens.

Solutions

  1. Correct the --process-allow entry to satisfy the process:spawn capability grammar
  2. Read the validate_capability error suffix for the exact rule violated
  3. Quote the argument and avoid unescaped shell glob expansion

Example fix

// before
--process-allow '/usr/bin/my tool'
// after
--process-allow 'my-tool'
Defensive patterns

Strategy: validation

Validate before calling

let cap = format!("process:spawn:{entry}");
if astrid_core::capability_grammar::validate_capability(&cap).is_err() { eprintln!("invalid process-allow entry: {entry}"); std::process::exit(2); }

Type guard

fn valid_spawn(entry: &str) -> bool { astrid_core::capability_grammar::validate_capability(&format!("process:spawn:{entry}")).is_ok() }

Try / catch

if let Err(e) = build_caps_to_grant(&args) { eprintln!("{e:#}"); std::process::exit(2); }

Prevention

When it happens

Trigger: Passing --process-allow with an entry containing invalid characters, absolute paths where bare binary names are required (or vice versa), globs the grammar rejects, or empty/whitespace remnants after comma-splitting.

Common situations: Listing system binaries with full paths including spaces ('/usr/bin/my tool'), using shell-style wildcards unsupported by the grammar, or copy-pasting a comma-separated list with stray characters.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at crates/astrid-cli/src/commands/agent/mod.rs:448

/// grammar (no dots in segments, etc.). Catching invalid labels here
/// — before any IPC — prevents the kernel from accepting the agent
/// profile and then rejecting the follow-up grant, which would leave a
/// half-provisioned agent on disk.
fn build_caps_to_grant(args: &CreateArgs) -> Result<Vec<String>> {
    let mut caps: Vec<String> = Vec::new();
    if let Some(domains) = args.egress.as_deref() {
        for entry in domains.split(',').map(str::trim).filter(|s| !s.is_empty()) {
            let cap = format!("network:egress:{entry}");
            astrid_core::capability_grammar::validate_capability(&cap)
                .map_err(|e| anyhow::anyhow!("invalid --egress entry {entry:?}: {e}"))?;
            caps.push(cap);
        }
    }
    if let Some(cmds) = args.process_allow.as_deref() {
        for entry in cmds.split(',').map(str::trim).filter(|s| !s.is_empty()) {
            let cap = format!("process:spawn:{entry}");
            astrid_core::capability_grammar::validate_capability(&cap)
                .map_err(|e| anyhow::anyhow!("invalid --process-allow entry {entry:?}: {e}"))?;
            caps.push(cap);
        }
    }
    Ok(caps)
}

/// Apply the parsed quota deltas: `QuotaGet` to pull the new agent's
/// defaults, replay each requested field, single `QuotaSet`. A failure
/// here leaves the agent in place with default quotas — operator can
/// re-run `astrid quota set -a <name> ...` to retry.
async fn apply_initial_quotas(
    client: &mut AdminClient,
    principal: &PrincipalId,
    updates: &[QuotaField],
) -> Result<()> {
    let body = client
        .request(AdminRequestKind::QuotaGet {
            principal: principal.clone(),

View on GitHub (pinned to affd8760f4)