zeroclaw-labs/zeroclaw · error · anyhow::Error
auth_secret cannot be empty
Error message
auth_secret cannot be empty
What it means
Thrown by HttpRequestTool::validate_secret_name (crates/zeroclaw-tools/src/http_request.rs:265) when the auth_secret argument is an empty string. auth_secret must name an entry in [http_request.secrets] of config.toml; an empty name can never match one. Passing no auth_secret at all is fine (the parameter is optional), so this error specifically means the field was present but blank.
Source
Thrown at crates/zeroclaw-tools/src/http_request.rs:265
if let Some(obj) = headers.as_object() {
for (key, value) in obj {
let Some(str_val) = value.as_str() else {
anyhow::bail!("Header '{key}' value must be a string, got: {}", value);
};
let header_name = HeaderName::from_str(key)
.map_err(|e| anyhow::Error::msg(format!("Invalid header name '{key}': {e}")))?;
let header_value = HeaderValue::from_str(str_val).map_err(|e| {
anyhow::Error::msg(format!("Invalid value for header '{key}': {e}"))
})?;
result.insert(header_name, header_value);
}
}
Ok(result)
}
fn validate_secret_name(secret_name: &str) -> anyhow::Result<()> {
if secret_name.is_empty() {
anyhow::bail!("auth_secret cannot be empty");
}
if secret_name.len() > 64 {
anyhow::bail!("auth_secret must be 64 characters or fewer");
}
if !secret_name
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
{
anyhow::bail!(
"auth_secret must contain only ASCII letters, numbers, underscores, or hyphens"
);
}
Ok(())
}
fn resolve_auth_secret(&self, secret_name: &str) -> anyhow::Result<String> {
Self::validate_secret_name(secret_name)?;
self.reload_auth_secret(secret_name)View on GitHub (pinned to 88bb9c8533)
Solutions
- Omit the auth_secret field entirely when no Authorization header is needed.
- If auth is required, pass the real key name defined under [http_request.secrets], e.g. "api_token".
- Guard in the caller: only include auth_secret when the variable is non-empty.
Example fix
// before
let args = json!({"url": u, "auth_secret": secret_name_var}); // var is ""
// after
let mut args = json!({"url": u});
if !secret_name_var.is_empty() {
args["auth_secret"] = json!(secret_name_var);
} Defensive patterns
Strategy: validation
Validate before calling
fn auth_secret_arg(name: Option<&str>) -> Option<&str> {
name.filter(|n| !n.is_empty())
} Type guard
fn is_usable_secret_name(name: &str) -> bool {
!name.is_empty()
} Try / catch
let result = tool.execute(args).await?;
if let Some(err) = &result.error {
if err.contains("auth_secret cannot be empty") {
// drop the empty field and send an unauthenticated request if acceptable
}
} Prevention
- Omit auth_secret entirely instead of sending an empty string.
- Build args conditionally: only insert auth_secret when a non-empty name is configured.
- Treat null vs empty distinctly: null yields a different error ("must be a string").
When it happens
Trigger: args = {"url": u, "auth_secret": ""}; templates that interpolate an optional secret name variable which resolved to empty; JSON built with a default empty string instead of omitting the key; note auth_secret: null produces a different error ("'auth_secret' must be a string").
Common situations: Optional-auth code paths that always include the key; LLM tool calls that emit an empty auth_secret when unsure; config-driven header injection where the secret name variable was never set.
Related errors
- auth_secret must be 64 characters or fewer
- auth_secret must contain only ASCII letters, numbers, unders
- environment-backed auth_secret '{inner}' must contain only A
- auth_secret requires a config.toml path
- auth_secret '{secret_name}' is empty after decryption
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/86bc26e6f24802f9.
Report an issue: GitHub.