{"record":{"id":"0011e7d6c88e008b","repo":"HKUDS/DeepTutor","slug":"local-llm-failed-streaming-e-non-streaming-e2","errorCode":null,"errorMessage":"Local LLM failed: streaming={e}, non-streaming={e2}","messagePattern":"Local LLM failed: streaming=(.+?), non-streaming=(.+?)","errorType":"error_code","errorClass":"LLMAPIError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/llm/local_provider.py","lineNumber":373,"sourceCode":"        raise  # Re-raise LLM errors as-is\n    except Exception as e:\n        # Streaming failed, fall back to non-streaming\n        logger.warning(\"Streaming failed (%s), falling back to non-streaming\", e)\n\n        try:\n            content = await complete(\n                prompt=prompt,\n                system_prompt=system_prompt,\n                model=model,\n                api_key=api_key,\n                base_url=base_url,\n                messages=messages,\n                **kwargs,\n            )\n            if content:\n                yield content\n        except Exception as e2:\n            raise LLMAPIError(\n                f\"Local LLM failed: streaming={e}, non-streaming={e2}\",\n                provider=\"local\",\n            )\n\n\nasync def fetch_models(\n    base_url: str,\n    api_key: str | None = None,\n) -> list[str]:\n    \"\"\"\n    Fetch available models from local LLM server.\n\n    Supports:\n    - Ollama (/api/tags)\n    - OpenAI-compatible (/models)\n\n    Args:\n        base_url: Base URL for the local server","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/llm/local_provider.py#L355-L391","documentation":"stream() falls back to non-streaming complete() when streaming fails; if both attempts raise, the provider gives up and wraps the combined failure in LLMAPIError (provider='local') without leaking either traceback.","triggerScenarios":"Streaming raises (network drop, non-200) and the subsequent non-streaming retry also raises — e.g. the local server went down mid-request, or the endpoint is entirely unreachable so both paths fail identically.","commonSituations":"Local server crashed or was restarted during a session; wrong port/URL so both connection attempts fail; firewall/DNS failure.","solutions":["Check that the local LLM server is running and reachable (curl the base_url).","Fix base_url/model configuration if both paths fail immediately.","Check server logs for crashes (OOM is common with large models)."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"import socket\nfrom urllib.parse import urlparse\n\ndef endpoint_reachable(base_url: str, timeout=2) -> bool:\n    p = urlparse(base_url)\n    try:\n        socket.create_connection((p.hostname, p.port or 80), timeout=timeout).close()\n        return True\n    except OSError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    async for chunk in provider.stream(messages): ...\nexcept LLMAPIError:\n    switch_to_backup_provider_or_report('local server unreachable')","preventionTips":["Run the local server under a supervisor (auto-restart)","Keep a secondary provider configured for failover","Health-check the endpoint before long streaming sessions"],"tags":["local-llm","fallback-failed","network"],"backgroundTag":"llm-provider-unavailable","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}