sigoden/aichat · error

(type: )

Error message

{message} (type: {typ})

What it means

The upstream API returned a non-2xx response whose JSON body contains an error object with 'type' and 'message' fields (the OpenAI/Gemini-style error envelope). The message is the provider's own description (e.g. 'rate limit exceeded', 'invalid api key') and the type is the provider's error classification. This branch fires only when the response parsed as JSON with an error object.

Solutions

  1. Check the error type against known provider classes (rate_limit_error, authentication_error, invalid_request_error) and branch accordingly
  2. Retry with exponential backoff and jitter for rate-limit or transient server error types
  3. For authentication errors, prompt the user to re-validate credentials instead of retrying
  4. Log the full response body at debug level to preserve diagnostics the message alone lacks
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at src/client/common.rs:503 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at src/client/common.rs:503

pub fn noop_prepare_rerank<T>(_client: &T, _data: &RerankData) -> Result<RequestData> {
    bail!("The client doesn't support rerank api")
}

pub async fn noop_rerank(_builder: RequestBuilder, _model: &Model) -> Result<RerankOutput> {
    bail!("The client doesn't support rerank api")
}

pub fn catch_error(data: &Value, status: u16) -> Result<()> {
    if (200..300).contains(&status) {
        return Ok(());
    }
    debug!("Invalid response, status: {status}, data: {data}");
    if let Some(error) = data["error"].as_object() {
        if let (Some(typ), Some(message)) = (
            json_str_from_map(error, "type"),
            json_str_from_map(error, "message"),
        ) {
            bail!("{message} (type: {typ})");
        } else if let (Some(typ), Some(message)) = (
            json_str_from_map(error, "code"),
            json_str_from_map(error, "message"),
        ) {
            bail!("{message} (code: {typ})");
        }
    } else if let Some(error) = data["errors"][0].as_object() {
        if let (Some(code), Some(message)) = (
            error.get("code").and_then(|v| v.as_u64()),
            json_str_from_map(error, "message"),
        ) {
            bail!("{message} (status: {code})")
        }
    } else if let Some(error) = data[0]["error"].as_object() {
        if let (Some(status), Some(message)) = (
            json_str_from_map(error, "status"),
            json_str_from_map(error, "message"),
        ) {

View on GitHub (pinned to 82976d349a)