{"record":{"id":"c150f440b8d01d3d","repo":"sigoden/aichat","slug":"unknown-client-client","errorCode":null,"errorMessage":"Unknown client '{client}'","messagePattern":"Unknown client '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/client/macros.rs","lineNumber":99,"sourceCode":"            })\n        }\n\n        pub fn list_client_types() -> Vec<&'static str> {\n            let mut client_types: Vec<_> = vec![$($client::NAME,)+];\n            client_types.extend($crate::client::OPENAI_COMPATIBLE_PROVIDERS.iter().map(|(name, _)| *name));\n            client_types\n        }\n\n        pub async fn create_client_config(client: &str) -> anyhow::Result<(String, serde_json::Value)> {\n            $(\n                if client == $client::NAME && client != $crate::client::OpenAICompatibleClient::NAME {\n                    return create_config(&$client::PROMPTS, $client::NAME).await\n                }\n            )+\n            if let Some(ret) = create_openai_compatible_client_config(client).await? {\n                return Ok(ret);\n            }\n            anyhow::bail!(\"Unknown client '{}'\", client)\n        }\n\n        static ALL_CLIENT_NAMES: std::sync::OnceLock<Vec<String>> = std::sync::OnceLock::new();\n\n        pub fn list_client_names(config: &$crate::config::Config) -> Vec<&'static String> {\n            let names = ALL_CLIENT_NAMES.get_or_init(|| {\n                config\n                    .clients\n                    .iter()\n                    .flat_map(|v| match v {\n                        $(ClientConfig::$config(c) => vec![$client::name(c).to_string()],)+\n                        ClientConfig::Unknown => vec![],\n                    })\n                    .collect()\n            });\n            names.iter().collect()\n        }\n","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/sigoden/aichat/blob/82976d349ad97ac9aae0655ad631dace5e2a6385/src/client/macros.rs#L81-L117","documentation":"Raised by the `create_config` macro expansion (src/client/macros.rs:99): after trying every builtin client and the generic OpenAI-compatible config path, the given client name matched nothing, so creation aborts with \"Unknown client '<name>'\". The client name in config is not one this build supports.","triggerScenarios":"Calling create_config (via client macro) with a client string that is not one of the macro-listed client names and not resolvable as an OpenAI-compatible client (no matching OpenAICompatibleClient::NAME type / api_base setup).","commonSituations":"Typo in config's client field (e.g. 'openiai'); using a client name from a different/newer library version; configuring a provider that is only reachable via the openai-compatible path but missing api_base/type fields; renamed client in an upgrade.","solutions":["Fix the client name to one of the supported values (see list_client_names output).","If the provider is OpenAI-compatible, set client_config type to the OpenAI-compatible client name and provide api_base and api_key.","Upgrade or downgrade the library so the desired client exists in this build.","Check the CHANGELOG for client renames if this worked before an upgrade."],"exampleFix":"// before (config)\n\"client\": \"openiai\"\n// after\n\"client\": \"openai\"","handlingStrategy":"validation","validationCode":"let supported = list_client_names(&config);\nif !supported.iter().any(|n| n.as_str() == client) {\n    anyhow::bail!(\"client '{}' not supported; choose one of {:?}\", client, supported);\n}","typeGuard":"fn is_known_client(client: &str, config: &Config) -> bool {\n    list_client_names(config).iter().any(|n| n.as_str() == client)\n}","tryCatchPattern":"match create_config(client).await {\n    Err(e) if e.to_string().starts_with(\"Unknown client\") => {\n        eprintln!(\"Supported clients: {:?}\", list_client_names(&config));\n    }\n    other => other,\n}","preventionTips":["Copy client names from list_client_names output rather than typing them.","For custom providers use the openai-compatible path with type/api_base/api_key set.","Check client renames after library upgrades.","Validate config files with a schema check before loading."],"tags":["config","invalid-value","rust","cli"],"backgroundTag":"invalid-config-value","analyzedSha":"82976d349ad97ac9aae0655ad631dace5e2a6385","analyzedAt":"2026-09-09T18:33:06.139Z","contentChangedAt":"2026-09-09T18:33:06.139Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}