sigoden/aichat · error

Unknown client

Error message

Unknown client '{client}'

What it means

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.

Solutions

  1. Fix the client name to one of the supported values (see list_client_names output).
  2. If the provider is OpenAI-compatible, set client_config type to the OpenAI-compatible client name and provide api_base and api_key.
  3. Upgrade or downgrade the library so the desired client exists in this build.
  4. Check the CHANGELOG for client renames if this worked before an upgrade.

Example fix

// before (config)
"client": "openiai"
// after
"client": "openai"
Defensive patterns

Strategy: validation

Validate before calling

let supported = list_client_names(&config);
if !supported.iter().any(|n| n.as_str() == client) {
    anyhow::bail!("client '{}' not supported; choose one of {:?}", client, supported);
}

Type guard

fn is_known_client(client: &str, config: &Config) -> bool {
    list_client_names(config).iter().any(|n| n.as_str() == client)
}

Try / catch

match create_config(client).await {
    Err(e) if e.to_string().starts_with("Unknown client") => {
        eprintln!("Supported clients: {:?}", list_client_names(&config));
    }
    other => other,
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of sigoden/aichat@82976d349a (2026-09-09). Data as JSON: /api/errors/c150f440b8d01d3d. Report an issue: GitHub.

Appendix: source

Thrown at src/client/macros.rs:99

            })
        }

        pub fn list_client_types() -> Vec<&'static str> {
            let mut client_types: Vec<_> = vec![$($client::NAME,)+];
            client_types.extend($crate::client::OPENAI_COMPATIBLE_PROVIDERS.iter().map(|(name, _)| *name));
            client_types
        }

        pub async fn create_client_config(client: &str) -> anyhow::Result<(String, serde_json::Value)> {
            $(
                if client == $client::NAME && client != $crate::client::OpenAICompatibleClient::NAME {
                    return create_config(&$client::PROMPTS, $client::NAME).await
                }
            )+
            if let Some(ret) = create_openai_compatible_client_config(client).await? {
                return Ok(ret);
            }
            anyhow::bail!("Unknown client '{}'", client)
        }

        static ALL_CLIENT_NAMES: std::sync::OnceLock<Vec<String>> = std::sync::OnceLock::new();

        pub fn list_client_names(config: &$crate::config::Config) -> Vec<&'static String> {
            let names = ALL_CLIENT_NAMES.get_or_init(|| {
                config
                    .clients
                    .iter()
                    .flat_map(|v| match v {
                        $(ClientConfig::$config(c) => vec![$client::name(c).to_string()],)+
                        ClientConfig::Unknown => vec![],
                    })
                    .collect()
            });
            names.iter().collect()
        }

View on GitHub (pinned to 82976d349a)