sigoden/aichat · error · anyhow::Error

Miss

Error message

Miss '{}'

What it means

A macro-generated config getter in src/client/macros.rs requires a value for a configuration field, looked up first from the environment variable `<CONFIG_NAME>_<FIELD>` (uppercased) and then from the config struct itself. When both are absent, it throws `Miss '<field>'`. This is the library's way of enforcing that every required client/config field is populated.

Solutions

  1. Set the corresponding environment variable `<CONFIG_PREFIX>_<FIELD>` (e.g. `export OPENAI_API_KEY=sk-...`).
  2. Add the field to the provider's config file / clients section so `self.config.$field_name` is populated.
  3. Verify the env var name matches `{client-name}_{field}` uppercased with an underscore separator.

Example fix

// before
$ llm 'hello'
Error: Miss 'api_key'

// after
export OPENAI_API_KEY=sk-...
$ llm 'hello'
Defensive patterns

Strategy: validation

Validate before calling

// Rust
let env_name = format!("{}_{}", client_name, field).to_ascii_uppercase();
if std::env::var(&env_name).is_err() && config_get_field(field).is_none() {
    return Err(anyhow!("{} must be set via {} or config", field, env_name));
}

Prevention

When it happens

Trigger: Calling any accessor generated by this macro (e.g. getters for api_key, base_url, etc.) when neither the `{PREFIX}_{FIELD}` environment variable is set nor `self.config.$field_name` holds a value.

Common situations: Running the CLI without exporting the expected environment variable (e.g. OPENAI_API_KEY), having an empty string normalized away, or misspelling the env var name (wrong prefix, lowercase).

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/client/macros.rs:235

                let request_data = $prepare_rerank(self, data)?;
                let builder = self.request_builder(client, request_data);
                $rerank(builder, self.model()).await
            }
        }
    };
}

#[macro_export]
macro_rules! config_get_fn {
    ($field_name:ident, $fn_name:ident) => {
        fn $fn_name(&self) -> anyhow::Result<String> {
            let env_prefix = Self::name(&self.config);
            let env_name =
                format!("{}_{}", env_prefix, stringify!($field_name)).to_ascii_uppercase();
            std::env::var(&env_name)
                .ok()
                .or_else(|| self.config.$field_name.clone())
                .ok_or_else(|| anyhow::anyhow!("Miss '{}'", stringify!($field_name)))
        }
    };
}

#[macro_export]
macro_rules! unsupported_model {
    ($name:expr) => {
        anyhow::bail!("Unsupported model '{}'", $name)
    };
}

View on GitHub (pinned to 82976d349a)