{"record":{"id":"5ca15931aac0679a","repo":"zeroclaw-labs/zeroclaw","slug":"auth-secret-secret-name-references-environment","errorCode":null,"errorMessage":"auth_secret '{secret_name}' references environment variable '{env_name}', but it is empty","messagePattern":"auth_secret '(.+?)' references environment variable '(.+?)', but it is empty","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/http_request.rs","lineNumber":435,"sourceCode":"        Ok(text)\n    }\n}\n\nfn resolve_env_backed_auth_secret(\n    secret_name: &str,\n    raw_secret: &str,\n) -> anyhow::Result<Option<String>> {\n    let Some(env_name) = env_secret_reference(raw_secret)? else {\n        return Ok(None);\n    };\n\n    let value = std::env::var(env_name).map_err(|e| {\n        anyhow::Error::msg(format!(\n            \"auth_secret '{secret_name}' references environment variable '{env_name}', but it could not be read: {e}\"\n        ))\n    })?;\n    if value.is_empty() {\n        anyhow::bail!(\n            \"auth_secret '{secret_name}' references environment variable '{env_name}', but it is empty\"\n        );\n    }\n    Ok(Some(value))\n}\n\nfn env_secret_reference(raw_secret: &str) -> anyhow::Result<Option<&str>> {\n    let Some(inner) = raw_secret\n        .strip_prefix(\"${\")\n        .and_then(|value| value.strip_suffix('}'))\n    else {\n        return Ok(None);\n    };\n\n    if inner.is_empty() {\n        anyhow::bail!(\n            \"environment-backed auth_secret references an empty environment variable name\"\n        );","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/http_request.rs#L417-L453","documentation":"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.","triggerScenarios":"[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.","commonSituations":"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.","solutions":["Set the environment variable to a non-empty value where the agent runs and re-invoke the tool.","Search the environment for the offending definition (empty export in .profile/.env/compose file) and fix or remove it.","Add a startup check that fails fast when any referenced ${VAR} is missing or empty."],"exampleFix":"# before\nexport API_TOKEN=   # set but empty -> error on use\n\n# after\nexport API_TOKEN=\"Bearer abc123\"","handlingStrategy":"validation","validationCode":"fn env_backed_secret_ready(env_name: &str) -> bool {\n    std::env::var(env_name).map(|v| !v.is_empty()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"let result = tool.execute(args).await?;\nif let Some(err) = &result.error {\n    if err.contains(\"but it is empty\") {\n        // the named env var exists but is blank: fix the deployment environment\n    } else if err.contains(\"could not be read\") {\n        // the variable is unset entirely\n    }\n}","preventionTips":["Add a preflight check for every ${VAR} referenced in [http_request.secrets]: present AND non-empty.","Audit .env files, unit files, and compose files for VAR= lines with no value.","Prefer failing the whole deployment over failing per-request on empty credentials."],"tags":["http","auth","secrets","environment","zeroclaw"],"backgroundTag":"missing-env-var","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}