{"record":{"id":"d7dbb910bae953a2","repo":"zeroclaw-labs/zeroclaw","slug":"grok-cli-does-not-accept-api-key-use-grok-login","errorCode":null,"errorMessage":"grok_cli does not accept api_key; use `grok login`, or export `XAI_API_KEY` and list it in the alias env_passthrough","messagePattern":"grok_cli does not accept api_key; use `grok login`, or export `XAI_API_KEY` and list it in the alias env_passthrough","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-providers/src/factory.rs","lineNumber":1530,"sourceCode":"    }\n\n    fn fallback_auth_ready(&self, _key: Option<&str>, _opts: &ModelProviderRuntimeOptions) -> bool {\n        true\n    }\n}\n\nimpl FamilyProviderFactory for GrokCliModelProviderConfig {\n    const ENDPOINT: ProviderEndpoint = ProviderEndpoint::CliBacked;\n\n    fn create_provider(\n        &self,\n        alias: &str,\n        key: Option<&str>,\n        _api_url: Option<&str>,\n        opts: &ModelProviderRuntimeOptions,\n    ) -> Result<Box<dyn ModelProvider>> {\n        if has_api_key(key) {\n            anyhow::bail!(\n                \"grok_cli does not accept api_key; use `grok login`, or export `XAI_API_KEY` and list it in the alias env_passthrough\"\n            );\n        }\n        Ok(Box::new(\n            crate::grok_cli::GrokCliModelProvider::builder(alias)\n                .binary_path(self.binary_path.as_deref())\n                .working_directory(&self.working_directory)\n                .env_passthrough(self.env_passthrough.clone())\n                .extra_args(self.extra_args.clone())\n                .max_acp_stdout_bytes(self.max_acp_stdout_bytes)\n                .timeout_secs(self.base.timeout_secs)\n                // Optional send-path only: alias `vision = true` makes\n                // ZeroClaw emit ACP image blocks. Grok still advertises\n                // image=false through 0.2.118 and does not reliably use the\n                // pixels; leave unset in production until upstream vision works.\n                .vision_enabled(opts.vision == Some(true))\n                .build()?,\n        ))","sourceCodeStart":1512,"sourceCodeEnd":1548,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/factory.rs#L1512-L1548","documentation":"The grok_cli family wraps the local grok CLI over ACP and authenticates through the CLI's own stored login (grok login), never through an api_key. The factory therefore refuses to construct the provider when a non-empty api_key is present (has_api_key true), and the message names the two supported routes.","triggerScenarios":"Creating a grok_cli alias while api_key is set from config or resolved from environment - for example copying an xai (HTTP) alias config to grok_cli and leaving the key in place, or an exported XAI_API_KEY being picked up as the alias key.","commonSituations":"Migrating alias configs between xai and grok_cli families; XAI_API_KEY exported globally and auto-resolved as the provider key; templates that set api_key on every alias.","solutions":["Remove api_key from the grok_cli alias config and environment so the CLI's own login is used","Run `grok login` once so the CLI has stored credentials","If you want key-based xAI access, use the xai family provider with api_key instead of grok_cli","To hand XAI_API_KEY to the CLI process, list it in the alias env_passthrough, not api_key"],"exampleFix":"# before\n[model_provider.grok]\nfamily = \"grok_cli\"\napi_key = \"xai-...\"\n\n# after\n[model_provider.grok]\nfamily = \"grok_cli\"\n# authenticate via `grok login`; optional:\n# env_passthrough = [\"XAI_API_KEY\"]","handlingStrategy":"validation","validationCode":"// Strip the key before factory construction for CLI-backed families\nlet key = if family == \"grok_cli\" { None } else { key };\nlet provider = factory.create_provider(alias, key, api_url, &opts)?;","typeGuard":null,"tryCatchPattern":"match factory.create_provider(alias, key, api_url, &opts) {\n    Ok(p) => Ok(p),\n    Err(e) if e.to_string().contains(\"grok_cli does not accept api_key\") => {\n        // config bug: remove api_key, or switch family to \"xai\" for key auth\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Do not copy api_key when cloning xai aliases to grok_cli","Keep XAI_API_KEY out of the alias key slot; use env_passthrough if the CLI needs it","Run `grok login` once per machine before using grok_cli aliases","Validate alias configs against family-specific key rules at load time"],"tags":["grok-cli","config","factory","auth","rust"],"backgroundTag":"invalid-provider-config","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}