zeroclaw-labs/zeroclaw · error

{var_name} not found or empty in .env

Error message

{var_name} not found or empty in .env

What it means

read_env_var resolves a variable strictly from the workspace .env file (not the process environment), parsing KEY=VALUE lines with optional export prefixes, comments, and quoted values. It bails when the key is absent or its parsed value is empty; this is how the image providers surface 'no API key configured'.

Source

Thrown at crates/zeroclaw-tools/src/linkedin_client.rs:919

            .with_context(|| format!("Failed to read {}", env_path.display()))?;

        for line in content.lines() {
            let line = line.trim();
            if line.starts_with('#') || line.is_empty() {
                continue;
            }
            let line = line.strip_prefix("export ").map(str::trim).unwrap_or(line);
            if let Some((key, value)) = line.split_once('=')
                && key.trim() == var_name
            {
                let val = LinkedInClient::parse_env_value(value);
                if !val.is_empty() {
                    return Ok(val);
                }
            }
        }

        anyhow::bail!("{var_name} not found or empty in .env")
    }

    fn http_client() -> reqwest::Client {
        zeroclaw_config::schema::build_runtime_proxy_client_with_timeouts(
            "tool.linkedin.image",
            60, // image gen can be slow
            10,
        )
    }

    // ── Stability AI ────────────────────────────────────────────

    async fn try_stability(
        &self,
        prompt: &str,
        output_dir: &Path,
        base_name: &str,
    ) -> anyhow::Result<PathBuf> {

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Add an uncommented, non-empty KEY=value line to the .env inside the exact workspace_dir the client was constructed with
  2. Compare the variable name against the provider's api_key_env setting in config
  3. If you rely on process env vars, copy them into .env — this reader never consults the process environment

Example fix

# before
# OPENAI_API_KEY=sk-...
OPENAI_APIKEY=sk-...

# after
OPENAI_API_KEY=sk-...
Defensive patterns

Strategy: validation

Validate before calling

fn env_var_present(dir: &Path, key: &str) -> anyhow::Result<()> {
    let content = std::fs::read_to_string(dir.join(".env")).context("workspace .env missing")?;
    let ok = content.lines().any(|l| {
        let l = l.trim().strip_prefix("export ").map(str::trim).unwrap_or(l.trim());
        match l.split_once('=') {
            Some((k, v)) => k.trim() == key && !v.trim().trim_matches('"').trim_matches('\'').is_empty(),
            None => false,
        }
    });
    anyhow::ensure!(ok, "{key} missing or empty in .env");
    Ok(())
}

Try / catch

Catch and report as configuration: name the missing variable (it is embedded in the message) and the workspace path searched — do not retry until the file is fixed.

Prevention

When it happens

Trigger: The key is missing from .env; the line is commented out; the value is empty or only quotes; the workspace_dir contains no .env; or the provider's api_key_env setting names a different variable than the one stored in the file.

Common situations: Keys injected via docker/CI environment instead of the file; .env stored one directory above the workspace; spelling drift between the api_key_env config and the file.

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/294938bee603b3b3. Report an issue: GitHub.