sigoden/aichat · error · anyhow::Error

{err_msg}

Error message

{err_msg}

What it means

In src/config/mod.rs config-loading code, a per-client (or section) configuration value failed validation; the message is dynamic (`{err_msg}`), optionally augmented with the offending value and a note that an exact location cannot be pinpointed. The error is re-thrown via `anyhow!` and layered with context naming the failing field.

Solutions

  1. Read the full error chain (context) to find which config section failed.
  2. Fix the offending client entry's value/type in the config file.
  3. Compare against the documented config schema for your version after an upgrade.
  4. Temporarily simplify the config to bisect which entry is invalid.

Example fix

// before (config.yaml)
clients:
  - type: openai
    api_key: 12345   # wrong type

// after
clients:
  - type: openai
    api_key: "sk-..."
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate config parses before use
serde_yaml::from_str::<Config>(&std::fs::read_to_string("config.yaml")?)
    .map_err(|e| eprintln!("config invalid: {e}"));

Try / catch

// Rust
match load_config() {
    Err(e) => {
    for cause in e.chain() { eprintln!("caused by: {cause}"); }
    }
    Ok(c) => c,
}

Prevention

When it happens

Trigger: Deserializing/validating a config file where a `clients` entry (or similar section) has an invalid value; the raw parse error is converted into `err_msg` and, when the value can't be located, appended with "(Sorry for being unable to provide an exact location)".

Common situations: Hand-edited config.yaml with a wrong type or unknown enum for a client field; copied config from another tool version; schema drift after upgrading the CLI.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/config/mod.rs:2218

    fn load_from_file(config_path: &Path) -> Result<Self> {
        let err = || format!("Failed to load config at '{}'", config_path.display());
        let content = read_to_string(config_path).with_context(err)?;
        let config: Self = serde_yaml::from_str(&content)
            .map_err(|err| {
                let err_msg = err.to_string();
                let err_msg = if err_msg.starts_with(&format!("{CLIENTS_FIELD}: ")) {
                    // location is incorrect, get rid of it
                    err_msg
                        .split_once(" at line")
                        .map(|(v, _)| {
                            format!("{v} (Sorry for being unable to provide an exact location)")
                        })
                        .unwrap_or_else(|| "clients: invalid value".into())
                } else {
                    err_msg
                };
                anyhow!("{err_msg}")
            })
            .with_context(err)?;

        Ok(config)
    }

    fn load_dynamic(model_id: &str) -> Result<Self> {
        let provider = match model_id.split_once(':') {
            Some((v, _)) => v,
            _ => model_id,
        };
        let is_openai_compatible = OPENAI_COMPATIBLE_PROVIDERS
            .into_iter()
            .any(|(name, _)| provider == name);
        let client = if is_openai_compatible {
            json!({ "type": "openai-compatible", "name": provider })
        } else {
            json!({ "type": provider })

View on GitHub (pinned to 82976d349a)