{"record":{"id":"6ec68e43e69d4f65","repo":"zed-industries/zed","slug":"failed-to-connect-to-ollama-api","errorCode":null,"errorMessage":"Failed to connect to Ollama API: {} {}","messagePattern":"Failed to connect to Ollama API: (.+?) (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ollama/src/ollama.rs","lineNumber":326,"sourceCode":"        })\n        .extra_headers(extra_headers)\n        .body(AsyncBody::from(serde_json::to_string(&request)?))?;\n\n    let mut response = client.send(request).await?;\n    if response.status().is_success() {\n        let reader = BufReader::new(response.into_body());\n\n        Ok(reader\n            .lines()\n            .map(|line| match line {\n                Ok(line) => serde_json::from_str(&line).context(\"Unable to parse chat response\"),\n                Err(e) => Err(e.into()),\n            })\n            .boxed())\n    } else {\n        let mut body = String::new();\n        response.body_mut().read_to_string(&mut body).await?;\n        anyhow::bail!(\n            \"Failed to connect to Ollama API: {} {}\",\n            response.status(),\n            body,\n        );\n    }\n}\n\npub async fn get_models(\n    client: &dyn HttpClient,\n    api_url: &str,\n    api_key: Option<&str>,\n    extra_headers: &CustomHeaders,\n) -> Result<Vec<LocalModelListing>> {\n    let uri = format!(\"{api_url}/api/tags\");\n    let request = HttpRequest::builder()\n        .method(Method::GET)\n        .uri(uri)\n        .header(\"Accept\", \"application/json\")","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/ollama/src/ollama.rs#L308-L344","documentation":"Raised by stream_chat_completion (crates/ollama/src/ollama.rs:326) when the POST to {api_url}/api/chat returns a non-success HTTP status. Despite the wording, the TCP connection succeeded; Ollama (or a proxy in front of it) answered with an error status and the raw response body is appended to the message, e.g. '404 Not Found {\"error\":\"model \\\"llama3\\\" not found\"}'. The status plus body usually identify the exact cause: 404 model not present, 400 malformed request, 401/403 wrong api_key or proxy auth, or an HTML block page when api_url points at a non-Ollama server.","triggerScenarios":"Calling stream_chat_completion with a model name that is not pulled locally (404 'model ... not found'); a request body containing fields an older Ollama build rejects (400); api_url routed through a gateway/SSO that answers 401/403; api_url with a wrong path so /api/chat 404s; api_key sent to an Ollama instance that proxies to a cloud endpoint requiring auth.","commonSituations":"Model in Zed's Ollama settings doesn't match `ollama list` output (tag mismatch such as llama3 vs llama3:8b); 'ollama serve' running on another machine/container while api_url still says localhost; corporate proxy intercepting localhost-adjacent URLs; Ollama version predating the /api/chat streaming endpoint.","solutions":["Run `ollama list` on the host api_url points to, then make the model name and tag in settings match exactly; `ollama pull <model>` if it is missing.","Verify reachability with `curl <api_url>/api/tags` from the same machine; fix api_url (typically http://localhost:11434) or start `ollama serve`.","Read the status code in the message: 404 → model/route problem, 400 → request fields, 401/403 → api_key or proxy auth, 429 → back off.","Upgrade Ollama to a release that supports the /api/chat request fields you send."],"exampleFix":"// before (settings.json)\n\"language_models\": { \"ollama\": { \"api_url\": \"http://localhost:11434\", \"available_models\": [{ \"name\": \"llama3\" }] } }\n// error: Failed to connect to Ollama API: 404 Not Found {\"error\":\"model \\\"llama3\\\" not found\"}\n\n// after: `ollama pull llama3:8b`, then\n\"language_models\": { \"ollama\": { \"api_url\": \"http://localhost:11434\", \"available_models\": [{ \"name\": \"llama3:8b\" }] } }","handlingStrategy":"try-catch","validationCode":"// Rust caller: verify server + model before streaming\nlet models = ollama::get_models(&*client, api_url, api_key, &extra_headers).await?;\nanyhow::ensure!(\n    models.iter().any(|m| m.name == request.model),\n    \"model {} not present in `ollama list` at {api_url}\",\n    request.model\n);","typeGuard":"fn is_reachable_ollama(status: StatusCode) -> bool {\n    // /api/tags answering 200 means the base URL is an Ollama server\n    status.is_success()\n}","tryCatchPattern":"match ollama::stream_chat_completion(&*client, api_url, api_key, req, &headers).await {\n    Ok(stream) => { /* consume */ }\n    Err(err) => {\n        let msg = err.to_string();\n        if msg.starts_with(\"Failed to connect to Ollama API: 404\") {\n            // model or route missing: pull model / fix api_url\n        } else if msg.starts_with(\"Failed to connect to Ollama API: 401\")\n            || msg.starts_with(\"Failed to connect to Ollama API: 403\") {\n            // api_key / proxy auth problem\n        } else {\n            return Err(err);\n        }\n    }\n}","preventionTips":["Keep api_url pointing at a verified `ollama serve` instance (curl /api/tags once in setup)","Pull and pin exact model:tag names that appear in `ollama list`","Upgrade Ollama alongside client updates so /api/chat request fields stay supported","When routing through a proxy, exempt the Ollama host or configure its auth instead of sending stray api_keys"],"tags":["ollama","http","llm-provider","status-code","network"],"backgroundTag":"llm-provider-api-error","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}