zeroclaw-labs/zeroclaw · error · anyhow::Error
auth_secret '{secret_name}' is empty after decryption
Error message
auth_secret '{secret_name}' is empty after decryption What it means
Thrown by HttpRequestTool::reload_auth_secret (crates/zeroclaw-tools/src/http_request.rs:320) when a secret entry in [http_request.secrets] is recognized as encrypted (zeroclaw_config::secrets::SecretStore format), decrypts successfully, but yields an empty string. Decryption worked; the stored plaintext itself is empty. The tool refuses to send an empty Authorization header, because that would silently break auth.
Source
Thrown at crates/zeroclaw-tools/src/http_request.rs:320
"Failed to parse config file {} for auth_secret '{secret_name}': {e}",
config_path.display()
))
})?;
let raw_secret = config
.http_request
.secrets
.get(secret_name)
.filter(|secret| !secret.is_empty())
.ok_or_else(|| anyhow::Error::msg(format!("auth_secret '{secret_name}' not found")))?;
let secret = if zeroclaw_config::secrets::SecretStore::is_encrypted(raw_secret) {
let zeroclaw_dir = config_path.parent().unwrap_or_else(|| Path::new("."));
let store =
zeroclaw_config::secrets::SecretStore::new(zeroclaw_dir, self.secrets_encrypt);
let plaintext = store.decrypt(raw_secret)?;
if plaintext.is_empty() {
anyhow::bail!("auth_secret '{secret_name}' is empty after decryption");
}
plaintext
} else {
raw_secret.clone()
};
if let Some(env_secret) = resolve_env_backed_auth_secret(secret_name, &secret)? {
Ok(env_secret)
} else {
Ok(secret)
}
}
fn apply_auth_secret(
&self,
headers: &mut HeaderMap,
auth_secret: Option<&str>,
) -> anyhow::Result<()> {View on GitHub (pinned to 88bb9c8533)
Solutions
- Re-encrypt the secret with a non-empty plaintext using zeroclaw's SecretStore and update the config.toml entry.
- Verify end-to-end: decrypt the stored value once after encryption and assert it is non-empty.
- If the secret is intentionally env-backed, encrypt "${VAR_NAME}" (the reference string) rather than the current env contents.
Example fix
# before api_token = "<encrypted empty string>" # decrypts to "" # after # re-run: zeroclaw secret encrypt with the real value api_token = "<encrypted 'Bearer real-token'>"
Defensive patterns
Strategy: validation
Validate before calling
// at startup, verify every configured secret decrypts to a non-empty value
for (name, raw) in &config.http_request.secrets {
if SecretStore::is_encrypted(raw) {
let plain = store.decrypt(raw)?;
anyhow::ensure!(!plain.is_empty(), "secret '{name}' decrypts to empty");
}
} Try / catch
let result = tool.execute(args).await?;
if let Some(err) = &result.error {
if err.contains("is empty after decryption") {
// re-encrypt the secret with its real value, then retry
}
} Prevention
- Run the encrypt workflow from a shell where the source value is verified non-empty.
- Add a post-encryption decrypt assertion to secret-management scripts.
- For env-sourced secrets, encrypt the "${VAR}" reference string, not the current env contents.
When it happens
Trigger: Running the secret-encrypt workflow while the source value was empty (e.g. exported an unset env var before encrypting); encrypting "" deliberately as a placeholder; a secret rotation script that encrypted an empty replacement; secrets_encrypt flag mismatches usually fail decryption with a different error, so this specifically means empty plaintext.
Common situations: Bootstrap scripts that encrypt ${VAR} when VAR was unset in that shell; CI pipelines creating placeholder secrets for new environments; copy-pasted encrypt commands run before the value was pasted in.
Related errors
- auth_secret cannot be empty
- auth_secret must be 64 characters or fewer
- auth_secret must contain only ASCII letters, numbers, unders
- auth_secret requires a config.toml path
- auth_secret '{secret_name}' references environment variable
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/e8932b943b4d865b.
Report an issue: GitHub.