From 08a4252c339593b6b21cee2222247efc798d4148 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Thu, 19 Feb 2026 13:55:45 +0200 Subject: [PATCH] download-models, show actionable error message when Ollama is not running --- CHANGELOG.md | 1 + haiku_rag_slim/haiku/rag/client.py | 58 ++++++++++++++++-------------- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4efc8e7e..8a15ffa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixed - Added `cachetools` as an explicit dependency (was only available transitively, causing `ModuleNotFoundError` for some installations) +- **download-models**: Show actionable error message when Ollama is not running instead of cryptic "All connection attempts failed" (#277) ## [0.30.1] - 2026-02-17 diff --git a/haiku_rag_slim/haiku/rag/client.py b/haiku_rag_slim/haiku/rag/client.py index 74482041..b1159876 100644 --- a/haiku_rag_slim/haiku/rag/client.py +++ b/haiku_rag_slim/haiku/rag/client.py @@ -1846,35 +1846,41 @@ class HaikuRAG: base_url = self._config.providers.ollama.base_url - async with httpx.AsyncClient(timeout=None) as client: - for model in sorted(required_models): - yield DownloadProgress(model=model, status="pulling") + try: + async with httpx.AsyncClient(timeout=None) as client: + for model in sorted(required_models): + yield DownloadProgress(model=model, status="pulling") - async with client.stream( - "POST", f"{base_url}/api/pull", json={"model": model} - ) as r: - async for line in r.aiter_lines(): - if not line: - continue - try: - data = json.loads(line) - status = data.get("status", "") - digest = data.get("digest", "") + async with client.stream( + "POST", f"{base_url}/api/pull", json={"model": model} + ) as r: + async for line in r.aiter_lines(): + if not line: + continue + try: + data = json.loads(line) + status = data.get("status", "") + digest = data.get("digest", "") - if digest and "total" in data: - yield DownloadProgress( - model=model, - status="downloading", - total=data.get("total", 0), - completed=data.get("completed", 0), - digest=digest, - ) - elif status: - yield DownloadProgress(model=model, status=status) - except json.JSONDecodeError: - pass + if digest and "total" in data: + yield DownloadProgress( + model=model, + status="downloading", + total=data.get("total", 0), + completed=data.get("completed", 0), + digest=digest, + ) + elif status: + yield DownloadProgress(model=model, status=status) + except json.JSONDecodeError: + pass - yield DownloadProgress(model=model, status="done") + yield DownloadProgress(model=model, status="done") + except httpx.ConnectError: + raise ConnectionError( + f"Cannot connect to Ollama at {base_url}. " + "Is Ollama running? Start it with 'ollama serve'." + ) def close(self): """Close the underlying store connection."""