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

environment-backed auth_secret '{inner}' must contain only A

Error message

environment-backed auth_secret '{inner}' must contain only ASCII letters, numbers, or underscores

What it means

Thrown by env_secret_reference (crates/zeroclaw-tools/src/http_request.rs:456) when the variable name inside a "${...}" secret reference contains characters other than ASCII letters, digits, and underscore. The allowed set mirrors what shell/POSIX environment variable names can safely contain, so references like "${MY-VAR}" or "${my.var}" are rejected at resolve time.

Source

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

    }
    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"
        );
    }
    if !inner.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
        anyhow::bail!(
            "environment-backed auth_secret '{inner}' must contain only ASCII letters, numbers, or underscores"
        );
    }
    Ok(Some(inner))
}

#[async_trait]
impl Tool for HttpRequestTool {
    fn name(&self) -> &str {
        "http_request"
    }

    fn description(&self) -> &str {
        "Make HTTP requests to external APIs. Supports GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS methods. \
        Security constraints: allowlist-only domains, local/private hosts blocked unless explicitly configured, configurable timeout and response size limits."
    }

    fn parameters_schema(&self) -> serde_json::Value {

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Rename the environment variable to letters/digits/underscore only (e.g. MY_VAR) and reference "${MY_VAR}".
  2. If the external name cannot change, export an alias: MY_VAR="$MY-VAR" in the process environment.
  3. Avoid nested or doubled brace syntax; exactly one ${...} wrapper is parsed.

Example fix

# before
[http_request.secrets]
api_token = "${MY-API-TOKEN}"

# after
# rename the variable (or alias it) then:
api_token = "${MY_API_TOKEN}"
Defensive patterns

Strategy: validation

Validate before calling

fn env_reference_name_valid(raw: &str) -> bool {
    match raw.strip_prefix("${").and_then(|v| v.strip_suffix('}')) {
        Some(inner) => {
            !inner.is_empty()
                && inner.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
        }
        None => true,
    }
}

Type guard

fn is_valid_env_reference_name(inner: &str) -> bool {
    !inner.is_empty() && inner.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
}

Try / catch

let result = tool.execute(args).await?;
if let Some(err) = &result.error {
    if err.contains("ASCII letters, numbers, or underscores") {
        // rename the referenced env var (alias hyphenated names) and retry
    }
}

Prevention

When it happens

Trigger: api_token = "${MY-VAR}" (hyphen), "${my.var}" (dot), "${VAR NAME}" (space), or "${VAR$}"; environment names inherited from systems that permit hyphens (some CI platforms, docker labels) pasted into the reference; doubled braces or nested ${${X}} leaving stray characters in the inner name.

Common situations: CI variable names with hyphens copied into config.toml; Windows-style or label-style identifiers used as env names; typos introducing punctuation into the reference.

Related errors


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