astrid-runtime/astrid · error

ASTRID_ENFORCED_DISTRO must not be empty

Error message

ASTRID_ENFORCED_DISTRO must not be empty

What it means

`resolve_init_distro_with` validates the `ASTRID_ENFORCED_DISTRO` environment variable that operators use to pin the distro source for `astrid init`. If the variable is set but empty, initialization fails closed rather than falling back to a default, ensuring an operator's enforced-distro policy is never silently bypassed.

Source

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

    resolve_init_distro_with(requested, std::env::var_os("ASTRID_ENFORCED_DISTRO"))
}

fn resolve_init_distro_with(
    requested: Option<String>,
    enforced: Option<OsString>,
) -> Result<String> {
    let Some(enforced) = enforced else {
        return non_empty_distro_source(requested).ok_or_else(|| {
            anyhow::anyhow!(
                "astrid init requires --distro <@owner/repo, URL, local Distro.toml, or .shuttle> unless ASTRID_ENFORCED_DISTRO is set by an embedding launcher; Astrid Runtime does not choose a product distro"
            )
        });
    };
    let enforced = enforced.into_string().map_err(|_| {
        anyhow::anyhow!("ASTRID_ENFORCED_DISTRO must contain a valid UTF-8 distro source")
    })?;
    if enforced.is_empty() {
        anyhow::bail!("ASTRID_ENFORCED_DISTRO must not be empty");
    }
    if requested.is_some() {
        anyhow::bail!(
            "astrid init cannot override the operator-enforced distro in ASTRID_ENFORCED_DISTRO"
        );
    }
    Ok(enforced)
}

fn non_empty_distro_source(source: Option<String>) -> Option<String> {
    source.filter(|source| !source.is_empty())
}

/// Route the root capsule-verb shorthand (`astrid <verb> [args…]`).
///
/// Built-in verbs never reach here — clap matches a declared `Commands`
/// variant before the `external_subcommand` catch-all. An unrecognised
/// token that is a near-miss of a built-in is rejected with a "did you

View on GitHub (pinned to affd8760f4)

Solutions

  1. Set `ASTRID_ENFORCED_DISTRO` to a valid non-empty distro source.
  2. Unset the variable entirely (`unset ASTRID_ENFORCED_DISTRO`) if no distro should be enforced, instead of exporting it empty.
  3. Fix the upstream script/config that produces the empty value.

Example fix

// before
export ASTRID_ENFORCED_DISTRO=""
astrid init
// after
unset ASTRID_ENFORCED_DISTRO
# or
export ASTRID_ENFORCED_DISTRO="internal/my-distro"
Defensive patterns

Strategy: validation

Validate before calling

let enforced = std::env::var("ASTRID_ENFORCED_DISTRO").unwrap_or_default();
if enforced.is_empty() && std::env::var_os("ASTRID_ENFORCED_DISTRO").is_some() {
    return Err("ASTRID_ENFORCED_DISTRO is set but empty; unset it or give it a value".into());
}

Type guard

fn has_valid_enforced_distro() -> bool {
    std::env::var("ASTRID_ENFORCED_DISTRO")
        .map(|v| !v.is_empty())
        .unwrap_or(true) // unset is fine; empty is not
}

Try / catch

match astrid::init(opts) {
    Err(e) if e.to_string().contains("ASTRID_ENFORCED_DISTRO must not be empty") => {
        eprintln!("unset ASTRID_ENFORCED_DISTRO or set a non-empty distro source");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Running `astrid init` (via `resolve_init_distro`) when `ASTRID_ENFORCED_DISTRO` is exported with an empty value, e.g. `ASTRID_ENFORCED_DISTRO= astrid init`.

Common situations: Shell scripts doing `export ASTRID_ENFORCED_DISTRO=$(cat policy_file)` where the file is empty or the command failed; CI configs defining the variable with no value; operators clearing the value intending to unset it.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


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