{"record":{"id":"ff3ac08435d04364","repo":"Hmbown/CodeWhale","slug":"kimi-code-membership-plan-api-key-not-found-get-a","errorCode":null,"errorMessage":"Kimi Code membership-plan API key not found. Get a plan key: {}. This route uses api.kimi.com/coding/v1 and does not import Kimi CLI credentials. Run 'codewhale auth set --provider moonshot', set {}, or add [{}] api_key.","messagePattern":"Kimi Code membership-plan API key not found\\. Get a plan key: (.+?)\\. This route uses api\\.kimi\\.com/coding/v1 and does not import Kimi CLI credentials\\. Run 'codewhale auth set --provider moonshot', set (.+?), or add \\[(.+?)\\] api_key\\.","errorType":"console","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/config.rs","lineNumber":6382,"sourceCode":"                   • api_key = \\\"<your-key>\\\"  in ~/.codewhale/config.toml\\n\\\n                   • already configured DeepSeek Harness? grant read-only access:\\n\\\n                        codewhale auth external-consent --provider deepseek --mode read-only\"\n            ),\n            ApiProvider::SiliconflowCn => anyhow::bail!(\n                \"SiliconFlow China API key not found. Get a key: {}. Run 'codewhale auth set --provider siliconflow-CN', \\\n                 set {}, or add [{}] api_key in ~/.codewhale/config.toml. \\\n                 [providers.siliconflow] remains a fallback when the CN table omits api_key.\",\n                provider\n                    .credential_url()\n                    .unwrap_or(\"https://cloud.siliconflow.com/account/ak\"),\n                provider.env_vars_label(),\n                provider_config_table_name(provider)?\n            ),\n            ApiProvider::Moonshot => {\n                let credential_help =\n                    credential_help_for_provider_route(provider, &self.deepseek_base_url());\n                if moonshot_base_url_is_exact_kimi_code(&self.deepseek_base_url()) {\n                    anyhow::bail!(\n                        \"Kimi Code membership-plan API key not found. Get a plan key: {}. This route uses api.kimi.com/coding/v1 and does not import Kimi CLI credentials. Run 'codewhale auth set --provider moonshot', set {}, or add [{}] api_key.\",\n                        credential_help\n                            .credential_url\n                            .unwrap_or(KIMI_CODE_MEMBERSHIP_PLAN_CONSOLE_URL),\n                        provider.env_vars_label(),\n                        provider_config_table_name(provider)?\n                    );\n                }\n                anyhow::bail!(\n                    \"Moonshot/Kimi API key not found. Get a key: {}. Run 'codewhale auth set --provider moonshot', \\\n                     set {}, or add [{}] api_key. \\\n                     For a Kimi Code plan key, set [providers.moonshot] base_url = \\\n                     \\\"https://api.kimi.com/coding/v1\\\" and model = \\\"kimi-for-coding\\\".\",\n                    credential_help\n                        .credential_url\n                        .unwrap_or(\"https://platform.kimi.ai/console/api-keys\"),\n                    provider.env_vars_label(),\n                    provider_config_table_name(provider)?","sourceCodeStart":6364,"sourceCodeEnd":6400,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/config.rs#L6364-L6400","documentation":"Raised for ApiProvider::Moonshot when the base URL is exactly the Kimi Code membership endpoint (https://api.kimi.com/coding/v1) and no plan key is configured. This route never imports Kimi CLI credentials; it requires a membership-plan API key, so the generic Moonshot guidance is replaced with plan-specific instructions.","triggerScenarios":"[providers.moonshot] base_url = \"https://api.kimi.com/coding/v1\" (exact match via moonshot_base_url_is_exact_kimi_code) with no stored key, env var, or api_key; users switching from pay-as-you-go Moonshot to a Kimi Code subscription without rotating credentials.","commonSituations":"Subscribing to Kimi Code membership and following the base_url/model switch steps but skipping the key step; mixing Kimi CLI login (OAuth) expectations with the plan-key route.","solutions":["Get a plan key from the Kimi console URL shown in the message.","Run codewhale auth set --provider moonshot.","Or export the Moonshot env var shown in the message.","Or add api_key under [providers.moonshot]."],"exampleFix":"# before\n[providers.moonshot]\nbase_url = \"https://api.kimi.com/coding/v1\"\nmodel = \"kimi-for-coding\"\n# no plan key configured\n\n# after\n[providers.moonshot]\nbase_url = \"https://api.kimi.com/coding/v1\"\nmodel = \"kimi-for-coding\"\napi_key = \"<plan-key>\"","handlingStrategy":"validation","validationCode":"fn kimi_code_route(cfg: &Config) -> bool {\n    moonshot_base_url_is_exact_kimi_code(&cfg.deepseek_base_url())\n}\n\nif kimi_code_route(&config) {\n    anyhow::ensure!(\n        moonshot_key_present(&config),\n        \"Kimi Code route requires a membership-plan key (not a Kimi CLI login)\"\n    );\n}","typeGuard":"fn is_kimi_code_membership_route(cfg: &Config) -> bool {\n    moonshot_base_url_is_exact_kimi_code(&cfg.deepseek_base_url())\n}","tryCatchPattern":"match config.deepseek_api_key() {\n    Err(e) if e.to_string().starts_with(\"Kimi Code membership-plan API key not found\") => {\n        run_auth_set(ApiProvider::Moonshot)?; // plan key, not CLI import\n        config.deepseek_api_key()\n    }\n    other => other,\n}","preventionTips":["Remember the coding/v1 route accepts plan keys only — Kimi CLI OAuth is never imported.","Keep pay-as-you-go and membership routes in separate provider entries to avoid key mix-ups.","After switching base_url, switch the credential source too."],"tags":["rust","moonshot","kimi","api-key","membership","config"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}