zeroclaw-labs/zeroclaw · error · anyhow::Error

Failed to parse Ollama response: {e}

Error message

Failed to parse Ollama response: {e}

What it means

Ollama returned a 2xx response, but the body failed to deserialize into the ChatResponse shape the provider expects (send_request_inner). The preceding WARN log records the deserialization error plus a body_excerpt, so the exact offending payload is recoverable from logs. This is schema drift between what Ollama returned and what this ZeroClaw build parses.

Source

Thrown at crates/zeroclaw-providers/src/ollama.rs:760

                sanitized
            );
        }

        let chat_response: ApiChatResponse = match serde_json::from_slice(&body) {
            Ok(r) => r,
            Err(e) => {
                let raw = String::from_utf8_lossy(&body);
                let sanitized = super::sanitize_api_error(&raw);
                ::zeroclaw_log::record!(
                    ERROR,
                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
                        .with_outcome(::zeroclaw_log::EventOutcome::Failure),
                    &format!(
                        "Ollama response deserialization failed: {e}. body_excerpt={}",
                        sanitized
                    )
                );
                anyhow::bail!("Failed to parse Ollama response: {e}");
            }
        };

        Ok(chat_response)
    }

    async fn send_request(
        &self,
        messages: Vec<Message>,
        model: &str,
        temperature: Option<f64>,
        should_auth: bool,
        tools: Option<&[serde_json::Value]>,
    ) -> anyhow::Result<ApiChatResponse> {
        let result = self
            .send_request_inner(
                &messages,
                model,

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Pull the WARN log line 'Ollama response deserialization failed: ... body_excerpt=...' and inspect the actual payload.
  2. Align versions: upgrade ZeroClaw to the release matching your Ollama version, or pin Ollama to the version the provider was built against.
  3. Remove intermediaries so the provider talks directly to Ollama's /api/chat.
  4. Confirm base_url is the Ollama native API root (e.g. http://localhost:11434), not an OpenAI-compatible /v1 endpoint.

Example fix

# before — OpenAI-compat shim behind the same port; wrong response shape
[providers.models.ollama.local]
base_url = "http://localhost:11434/v1"

# after — native Ollama API root
[providers.models.ollama.local]
base_url = "http://localhost:11434"
Defensive patterns

Strategy: try-catch

Validate before calling

# Smoke-test the wire shape before starting long jobs
curl -s http://localhost:11434/api/chat -d '{"model":"llama3","messages":[{"role":"user","content":"ping"}],"stream":false}' | jq -e '.message.content' >/dev/null && echo shape-ok

Try / catch

Catch the parse failure, then read the paired WARN log ('Ollama response deserialization failed: ... body_excerpt=...') to see the exact payload. Fix the shape mismatch (version drift, proxy, wrong base_url) instead of retrying — the response will fail identically.

Prevention

When it happens

Trigger: An Ollama upgrade adds/renames fields the parser treats as required; a reverse proxy in front of Ollama rewrites the JSON or substitutes a 200 HTML page; base_url targets a non-Ollama server whose /api/chat response shape differs.

Common situations: Upgrading Ollama ahead of the ZeroClaw version's schema (or vice versa); routing Ollama through a gateway that mangles bodies; pointing base_url at an OpenAI-compat shim that answers /api/chat with the wrong shape.

Understand the failure class

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/3a6f568f3442b408. Report an issue: GitHub.