{"record":{"id":"76d009435f6f2fdf","repo":"headroomlabs-ai/headroom","slug":"ollama-api-error-e","errorCode":null,"errorMessage":"Ollama API error: {e}","messagePattern":"Ollama API error: (.+?)","errorType":"exception","errorClass":"ConnectionError","httpStatus":null,"severity":"error","filePath":"headroom/memory/adapters/embedders.py","lineNumber":932,"sourceCode":"\n                # Detect dimension from first successful response\n                if self._detected_dimension is None:\n                    self._detected_dimension = len(embedding)\n\n                return embedding\n\n            except (httpx.ConnectError, httpx.TimeoutException, httpx.HTTPStatusError) as e:\n                last_error = e\n                delay = self.RETRY_DELAY_BASE * (2**attempt)\n                logger.warning(\n                    f\"Ollama API error (attempt {attempt + 1}/{self._max_retries}): {e}. \"\n                    f\"Retrying in {delay:.1f}s...\"\n                )\n                await asyncio.sleep(delay)\n\n            except Exception as e:\n                # Non-retryable error\n                raise ConnectionError(f\"Ollama API error: {e}\") from e\n\n        # All retries exhausted\n        raise ConnectionError(\n            f\"Ollama API failed after {self._max_retries} retries: {last_error}\"\n        ) from last_error\n\n    async def embed(self, text: str) -> np.ndarray:\n        \"\"\"Generate an embedding for a single text.\n\n        Args:\n            text: The text to embed.\n\n        Returns:\n            Normalized embedding vector as float32 numpy array.\n\n        Raises:\n            ConnectionError: If API call fails after retries.\n        \"\"\"","sourceCodeStart":914,"sourceCodeEnd":950,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/memory/adapters/embedders.py#L914-L950","documentation":"Inside OllamaEmbedder's retry loop, transient failures — httpx.ConnectError, httpx.TimeoutException, httpx.HTTPStatusError — are retried with backoff, but any other exception is immediately wrapped in ConnectionError('Ollama API error: {e}') with the original chained. This branch means a non-transient failure such as a 404 from an unknown model, a malformed request, or a response that isn't valid JSON for the expected schema.","triggerScenarios":"Calling embed()/embed_batch() against a local Ollama server where the configured embedding model (e.g. nomic-embed-text) has not been pulled, the model returns an unexpected payload, or the request body doesn't match the Ollama version's /api/embed contract.","commonSituations":"Fresh Ollama install without `ollama pull nomic-embed-text`; Ollama version mismatch (old /api/embeddings vs newer /api/embed endpoint shapes); model name typo in config; GPU Ollama crashing mid-request producing a non-HTTP error.","solutions":["Check the chained __cause__ — a 404 'model not found' means you must pull it: `ollama pull nomic-embed-text`.","Verify the server is the version you expect: curl http://localhost:11434/api/tags and confirm the model is listed.","Match the model name in OllamaEmbedder(model_name=...) exactly to `ollama list` output.","Upgrade/downgrade Ollama to match the API shape headroom targets.","Do not retry — this class is non-retryable by design."],"exampleFix":"# before\nemb = OllamaEmbedder(model_name=\"nomic-embed\")  # 404 -> ConnectionError\nawait emb.embed(\"hi\")\n\n# after (shell)\nollama pull nomic-embed-text\n# python\nemb = OllamaEmbedder(model_name=\"nomic-embed-text\")","handlingStrategy":"try-catch","validationCode":"import httpx\n\ndef ollama_model_ready(base_url: str, model: str) -> bool:\n    \"\"\"True if the local Ollama server lists the requested model.\"\"\"\n    try:\n        tags = httpx.get(f\"{base_url}/api/tags\", timeout=5).json()\n        return any(m[\"name\"] == model for m in tags.get(\"models\", []))\n    except httpx.HTTPError:\n        return False\n\nif not ollama_model_ready(\"http://localhost:11434\", \"nomic-embed-text\"):\n    raise SystemExit(\"ollama pull nomic-embed-text before embedding\")","typeGuard":null,"tryCatchPattern":"try:\n    vec = await emb.embed(text)\nexcept ConnectionError as e:\n    if \"Ollama API error\" in str(e) and \"404\" in str(e.__cause__):\n        raise SystemExit(\"model not pulled: run `ollama pull <model>`\") from e\n    raise","preventionTips":["`ollama pull` every embedding model as part of host provisioning.","Verify model names against `ollama list` output exactly (case-sensitive).","Treat this error class as permanent — fix the cause, don't retry."],"tags":["ollama","api","embeddings","non-retryable","local-model"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}