{"record":{"id":"57684fc6a03a6e12","repo":"zeroclaw-labs/zeroclaw","slug":"glm-api-key-not-set-or-invalid-format-expected-i","errorCode":null,"errorMessage":"GLM API key not set or invalid format. Expected 'id.secret'. Set GLM_API_KEY env var or run `zeroclaw quickstart --model-provider glm --api-key <id.secret>`.","messagePattern":"GLM API key not set or invalid format\\. Expected 'id\\.secret'\\. Set GLM_API_KEY env var or run `zeroclaw quickstart --model-provider glm --api-key <id\\.secret>`\\.","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-providers/src/glm.rs","lineNumber":99,"sourceCode":"\nimpl GlmModelProvider {\n    pub fn new(api_key: Option<&str>) -> Self {\n        let (id, secret) = api_key\n            .and_then(|k| k.split_once('.'))\n            .map(|(id, secret)| (id.to_string(), secret.to_string()))\n            .unwrap_or_default();\n\n        Self {\n            api_key_id: id,\n            api_key_secret: secret,\n            base_url: \"https://api.z.ai/api/paas/v4\".to_string(),\n            token_cache: Mutex::new(None),\n        }\n    }\n\n    fn generate_token(&self) -> anyhow::Result<String> {\n        if self.api_key_id.is_empty() || self.api_key_secret.is_empty() {\n            anyhow::bail!(\n                \"GLM API key not set or invalid format. Expected 'id.secret'. \\\n                 Set GLM_API_KEY env var or run `zeroclaw quickstart --model-provider glm --api-key <id.secret>`.\"\n            );\n        }\n\n        let now_ms = SystemTime::now()\n            .duration_since(UNIX_EPOCH)?\n            .as_millis() as u64;\n\n        // Check cache (valid for 3 minutes, token expires at 3.5 min)\n        if let Ok(cache) = self.token_cache.lock() {\n            if let Some((ref token, expiry)) = *cache {\n                if now_ms < expiry {\n                    return Ok(token.clone());\n                }\n            }\n        }\n","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/glm.rs#L81-L117","documentation":"GlmModelProvider could not build its JWT because the key is absent or lacks the 'id.secret' shape. GlmModelProvider::new splits the input on the first dot; an empty id or empty secret (including no dot at all) trips this bail, which names both remediation commands explicitly.","triggerScenarios":"GLM_API_KEY unset; key with no dot; key with an empty half such as '.secret' or 'id.'; passing None to the constructor; key with surrounding whitespace so one side trims empty.","commonSituations":"Env var forgotten in deployment; .env file not loaded; trailing newline in the secret; using an OpenAI-style sk-... key with the GLM provider by mistake.","solutions":["Export GLM_API_KEY as a dot-separated 'id.secret' pair","Or run: zeroclaw quickstart --model-provider glm --api-key <id.secret>","Trim whitespace/newlines when loading the key","Confirm on the Z.ai console that the key really has the id.secret form"],"exampleFix":"# before\nexport GLM_API_KEY=sk-abcdef123\n\n# after\nexport GLM_API_KEY=\"<key-id>.<key-secret>\"  # dot-separated, no spaces","handlingStrategy":"validation","validationCode":"fn glm_key_valid(key: &str) -> bool {\n    match key.trim().split_once('.') {\n        Some((id, secret)) => !id.is_empty() && !secret.is_empty(),\n        None => false,\n    }\n}\n\n// use before constructing the provider:\nlet key = std::env::var(\"GLM_API_KEY\")?;\nanyhow::ensure!(glm_key_valid(&key), \"GLM_API_KEY must look like id.secret\");","typeGuard":"fn glm_key_valid(key: &str) -> bool {\n    matches!(key.trim().split_once('.'), Some((id, s)) if !id.is_empty() && !s.is_empty())\n}","tryCatchPattern":"if let Err(e) = provider.chat_with_system(None, prompt, model, temp).await {\n    if e.to_string().starts_with(\"GLM API key not set\") {\n        return Err(anyhow::anyhow!(\"configure GLM_API_KEY before starting GLM jobs\"));\n    }\n    return Err(e);\n}","preventionTips":["Fail fast at startup: validate the id.secret shape before first use","Trim env values when loading; newlines break the split","Add a config lint for GLM keys in CI","Never reuse OpenAI-style sk- keys with the GLM provider"],"tags":["rust","zeroclaw","glm","api-key","missing-env-var","configuration"],"backgroundTag":"missing-api-key","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}