zeroclaw-labs/zeroclaw · error · anyhow::Error

auth_secret '{secret_name}' references environment variable

Error message

auth_secret '{secret_name}' references environment variable '{env_name}', but it is empty

What it means

Thrown by resolve_env_backed_auth_secret (crates/zeroclaw-tools/src/http_request.rs:435) when a secret's config value is an environment reference "${ENV_NAME}", the variable EXISTS, but its value is the empty string. This is distinct from the unset case, which fails earlier with "could not be read: environment variable not present". An empty credential would produce a broken Authorization header, so the tool rejects it explicitly.

Source

Thrown at crates/zeroclaw-tools/src/http_request.rs:435

        Ok(text)
    }
}

fn resolve_env_backed_auth_secret(
    secret_name: &str,
    raw_secret: &str,
) -> anyhow::Result<Option<String>> {
    let Some(env_name) = env_secret_reference(raw_secret)? else {
        return Ok(None);
    };

    let value = std::env::var(env_name).map_err(|e| {
        anyhow::Error::msg(format!(
            "auth_secret '{secret_name}' references environment variable '{env_name}', but it could not be read: {e}"
        ))
    })?;
    if value.is_empty() {
        anyhow::bail!(
            "auth_secret '{secret_name}' references environment variable '{env_name}', but it is empty"
        );
    }
    Ok(Some(value))
}

fn env_secret_reference(raw_secret: &str) -> anyhow::Result<Option<&str>> {
    let Some(inner) = raw_secret
        .strip_prefix("${")
        .and_then(|value| value.strip_suffix('}'))
    else {
        return Ok(None);
    };

    if inner.is_empty() {
        anyhow::bail!(
            "environment-backed auth_secret references an empty environment variable name"
        );

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Set the environment variable to a non-empty value where the agent runs and re-invoke the tool.
  2. Search the environment for the offending definition (empty export in .profile/.env/compose file) and fix or remove it.
  3. Add a startup check that fails fast when any referenced ${VAR} is missing or empty.

Example fix

# before
export API_TOKEN=   # set but empty -> error on use

# after
export API_TOKEN="Bearer abc123"
Defensive patterns

Strategy: validation

Validate before calling

fn env_backed_secret_ready(env_name: &str) -> bool {
    std::env::var(env_name).map(|v| !v.is_empty()).unwrap_or(false)
}

Try / catch

let result = tool.execute(args).await?;
if let Some(err) = &result.error {
    if err.contains("but it is empty") {
        // the named env var exists but is blank: fix the deployment environment
    } else if err.contains("could not be read") {
        // the variable is unset entirely
    }
}

Prevention

When it happens

Trigger: [http_request.secrets] api_token = "${API_TOKEN}" with `export API_TOKEN=` (set to empty) in the shell/unit file; CI/CD secrets defined but with an empty value; .env files with a trailing `API_TOKEN=` line; docker-compose secrets that resolve to empty strings in the container.

Common situations: Deployments where the secret is created in the platform UI but left blank; staged rollouts that define variables before values exist; shell profiles that reset the variable to empty; Kubernetes secrets created from empty literal values.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/5ca15931aac0679a. Report an issue: GitHub.