HKUDS/DeepTutor · error · LLMAPIError

Local LLM stream error: {error_text}

Error message

Local LLM stream error: {error_text}

What it means

The streaming request to the local LLM server returned a non-200 status; LLMAPIError carries the status code and the raw body so the caller can see why the server refused the stream.

Source

Thrown at deeptutor/services/llm/local_provider.py:303

        "temperature": kwargs.get("temperature", 0.7),
        "stream": True,
    }

    if kwargs.get("max_tokens"):
        data["max_tokens"] = kwargs["max_tokens"]

    timeout_value = kwargs.get("timeout", DEFAULT_TIMEOUT)
    timeout_seconds = (
        float(timeout_value) if isinstance(timeout_value, (int, float)) else DEFAULT_TIMEOUT
    )
    timeout = aiohttp.ClientTimeout(total=timeout_seconds)

    try:
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.post(url, json=data, headers=headers) as response:
                if response.status != 200:
                    error_text = await response.text()
                    raise LLMAPIError(
                        f"Local LLM stream error: {error_text}",
                        status_code=response.status,
                        provider="local",
                    )

                thinking_parser = _ThinkingBlockParser()

                async for line in response.content:
                    line_str = line.decode("utf-8").strip()

                    # Skip empty lines
                    if not line_str:
                        continue

                    # Handle SSE format
                    if line_str.startswith("data:"):
                        data_str = line_str[5:].strip()

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Inspect the embedded error_text for the server's own message.
  2. Pull/fix the model name; verify the server supports SSE streaming.
  3. Reduce prompt size if the server reports context overflow.
Defensive patterns

Strategy: retry

Validate before calling

import aiohttp

async def model_available(base_url: str, model: str) -> bool:
    async with aiohttp.ClientSession() as s, s.get(f'{base_url}/models') as r:
        models = (await r.json()).get('data', [])
        return any(m.get('id') == model for m in models)

Try / catch

try:
    async for chunk in provider.stream(messages): ...
except LLMAPIError as e:
    if e.status_code == 400:
        shrink_context_and_retry()
    elif e.status_code >= 500:
        await backoff_and_retry()

Prevention

When it happens

Trigger: session.post(url) inside stream() returns non-200: wrong model name (404), context length exceeded (400), server error (500), or unsupported streaming flag.

Common situations: Model not loaded in Ollama; local server that doesn't support stream=true; oversized prompt exceeding local context window.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/0e9a7dbc06667d7d. Report an issue: GitHub.