{"record":{"id":"9abc08756320e104","repo":"affaan-m/ECC","slug":"msg-9abc08","errorCode":null,"errorMessage":"{msg}","messagePattern":"\\{msg\\}","errorType":"exception","errorClass":"RateLimitError","httpStatus":429,"severity":"warning","filePath":"src/llm/providers/ollama.py","lineNumber":106,"sourceCode":"                        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":88,"sourceCodeEnd":119,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/src/llm/providers/ollama.py#L88-L119","documentation":"OllamaProvider.generate() raises RateLimitError when the exception message contains '429' or 'rate_limit'. Ollama is local and has no per-key quota, so this typically fires when OLLAMA_NUM_PARALLEL or OLLAMA_MAX_LOADED_MODELS is exceeded (older Ollama defaulted NUM_PARALLEL to 1), or when a reverse proxy/gateway in front of Ollama enforces 429s.","triggerScenarios":"More concurrent requests than OLLAMA_NUM_PARALLEL; a gateway/proxy in front of Ollama returning 429; an Ollama error whose text happens to contain 'rate_limit'.","commonSituations":"Parallel agent loops hitting a single local Ollama; OLLAMA_NUM_PARALLEL left at default; Ollama routed through nginx with rate limiting; a version change adding rate-limit-style errors for a busy GPU.","solutions":["Serialize Ollama calls or raise OLLAMA_NUM_PARALLEL in the server config.","Reduce concurrency of the calling code.","If behind a proxy, raise its rate limit.","Retry with exponential backoff on RateLimitError."],"exampleFix":"// before\noutput = provider.generate(llm_input)\n\n// after\nimport time\nfrom llm.core.interface import RateLimitError\n\nfor attempt in range(4):\n    try:\n        output = provider.generate(llm_input)\n        break\n    except RateLimitError:\n        if attempt == 3:\n            raise\n        time.sleep(2 ** attempt)","handlingStrategy":"retry","validationCode":"import os, httpx\n\ndef ollama_has_capacity(base_url: str) -> bool:\n    # OLLAMA_NUM_PARALLEL defaults vary; this is a liveness check only\n    try:\n        return httpx.get(f\"{base_url.rstrip('/')}/api/tags\", timeout=5).status_code == 200\n    except Exception:\n        return False","typeGuard":"from llm.core.interface import RateLimitError\n\ndef is_ollama_rate_limit(exc: BaseException) -> bool:\n    return isinstance(exc, RateLimitError)","tryCatchPattern":"import time\nfrom llm.core.interface import RateLimitError\n\nfor attempt in range(4):\n    try:\n        output = provider.generate(llm_input)\n        break\n    except RateLimitError:\n        if attempt == 3:\n            raise\n        time.sleep(2 ** attempt)","preventionTips":["Serialize Ollama calls or raise OLLAMA_NUM_PARALLEL on the server.","Don't fan out parallel requests to a single local Ollama instance.","If behind a proxy, size its rate limit to expected throughput."],"tags":["ollama","rate-limit","llm-provider","local-server","concurrency"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}