{"record":{"id":"a5cc3c26c28c679d","repo":"affaan-m/ECC","slug":"ollama-connection-failed-msg","errorCode":null,"errorMessage":"Ollama connection failed: {msg}","messagePattern":"Ollama connection failed: (.+?)","errorType":"exception","errorClass":"AuthenticationError","httpStatus":null,"severity":"error","filePath":"src/llm/providers/ollama.py","lineNumber":104,"sourceCode":"                tool_calls = [\n                    ToolCall(\n                        id=tc.get(\"id\", \"\"),\n                        name=tc.get(\"function\", {}).get(\"name\", \"\"),\n                        arguments=tc.get(\"function\", {}).get(\"arguments\", {}),\n                    )\n                    for tc in result[\"message\"][\"tool_calls\"]\n                ]\n\n            return LLMOutput(\n                content=content,\n                tool_calls=tool_calls,\n                model=model,\n                stop_reason=result.get(\"done_reason\"),\n            )\n        except Exception as e:\n            msg = str(e)\n            if \"401\" in msg or \"connection\" in msg.lower():\n                raise AuthenticationError(f\"Ollama connection failed: {msg}\", provider=ProviderType.OLLAMA) from e\n            if \"429\" in msg or \"rate_limit\" in msg.lower():\n                raise RateLimitError(msg, provider=ProviderType.OLLAMA) from e\n            if \"context\" in msg.lower() and \"length\" in msg.lower():\n                raise ContextLengthError(msg, provider=ProviderType.OLLAMA) from e\n            raise\n\n    def list_models(self) -> list[ModelInfo]:\n        return self._models.copy()\n\n    def validate_config(self) -> bool:\n        return bool(self.base_url)\n\n    def get_default_model(self) -> str:\n        return self.default_model\n","sourceCodeStart":86,"sourceCodeEnd":119,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/src/llm/providers/ollama.py#L86-L119","documentation":"OllamaProvider.generate() raises AuthenticationError with the message 'Ollama connection failed: ...' whenever the underlying exception message contains '401' OR the word 'connection'. Ollama runs as a local HTTP server (default http://localhost:11434) with no API key, so this almost always indicates the server is unreachable — not real authentication. The '401' branch is effectively a red herring for local Ollama; connection failures are the common cause.","triggerScenarios":"Ollama daemon not running; base_url pointing at a dead/unreachable address; OLLAMA_HOST env var wrong; firewall blocking the port; urllib.error.URLError whose message contains 'connection'.","commonSituations":"Fresh install where 'ollama serve' was never started; base_url configured for a remote host that is down; Ollama bound to 127.0.0.1 but the client uses a container hostname; an SSH tunnel closed; missing the model after first install.","solutions":["Start Ollama: run 'ollama serve' or verify the systemd service is up.","Confirm base_url with 'curl <base_url>/api/tags'.","Check OLLAMA_HOST / base_url resolves and is reachable from the client process.","Pull the requested model with 'ollama pull <model>' before calling generate().","Remember this maps to AuthenticationError even for connection failures — catch AuthenticationError, not ConnectionError."],"exampleFix":"// before\noutput = provider.generate(llm_input)\n\n// after\nimport httpx\nfrom llm.core.interface import AuthenticationError\n\ndef ensure_ollama(base_url: str) -> None:\n    try:\n        httpx.get(f\"{base_url.rstrip('/')}/api/tags\", timeout=5).raise_for_status()\n    except Exception:\n        import subprocess\n        subprocess.Popen([\"ollama\", \"serve\"])\n\ntry:\n    output = provider.generate(llm_input)\nexcept AuthenticationError as e:\n    if \"Ollama connection failed\" not in str(e):\n        raise\n    ensure_ollama(provider.base_url)\n    output = provider.generate(llm_input)","handlingStrategy":"validation","validationCode":"import httpx\n\ndef ollama_reachable(base_url: str, timeout: float = 5.0) -> bool:\n    try:\n        r = httpx.get(f\"{base_url.rstrip('/')}/api/tags\", timeout=timeout)\n        return r.status_code == 200\n    except Exception:\n        return False","typeGuard":"from llm.core.interface import AuthenticationError\n\ndef is_ollama_conn_error(exc: BaseException) -> bool:\n    return isinstance(exc, AuthenticationError) and \"Ollama connection failed\" in str(exc)","tryCatchPattern":"from llm.core.interface import AuthenticationError\n\ntry:\n    output = provider.generate(llm_input)\nexcept AuthenticationError as e:\n    if \"Ollama connection failed\" not in str(e):\n        raise  # real auth error, not a connection failure\n    start_ollama()\n    output = provider.generate(llm_input)","preventionTips":["Health-check base_url/api/tags before calling generate().","Run 'ollama serve' as a managed service, not a manual process.","Pre-pull models with 'ollama pull' so missing models don't surface as connection errors.","Remember Ollama connection failures are classified as AuthenticationError here — don't catch ConnectionError expecting them."],"tags":["ollama","connection","llm-provider","local-server"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}