{"record":{"id":"cf6aade659841a87","repo":"HKUDS/DeepTutor","slug":"the-model-returned-an-empty-response","errorCode":null,"errorMessage":"The model returned an empty response.","messagePattern":"The model returned an empty response\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/doctor.py","lineNumber":342,"sourceCode":"    from deeptutor.services.llm import complete\n\n    response = await complete(\n        model=str(config.model),\n        prompt=\"Reply with OK.\",\n        system_prompt=\"Reply with only OK.\",\n        binding=str(config.binding),\n        api_key=str(config.api_key or \"\"),\n        base_url=str(config.effective_url or config.base_url or \"\"),\n        api_version=config.api_version,\n        temperature=0,\n        extra_headers=config.extra_headers,\n        reasoning_effort=config.reasoning_effort,\n        max_retries=0,\n        allow_image_fallback=False,\n        max_tokens=64,\n    )\n    if not (response or \"\").strip():\n        raise RuntimeError(\"The model returned an empty response.\")\n\n\nasync def run_diagnostics(\n    *,\n    online: bool = False,\n    resolve_llm: Callable[[], Any] | None = None,\n    data_root: Path | None = None,\n    load_rag_config: Callable[[], dict[str, Any]] | None = None,\n    rag_preflight: Callable[[str], dict[str, Any]] | None = None,\n    online_probe: Callable[[Any], Awaitable[None]] | None = None,\n) -> DoctorReport:\n    \"\"\"Run setup diagnostics without network access unless ``online`` is set.\"\"\"\n    if resolve_llm is None:\n        from deeptutor.services.config import resolve_llm_runtime_config\n\n        resolve_llm = resolve_llm_runtime_config\n    if data_root is None:\n        from deeptutor.services.path_service import get_path_service","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/doctor.py#L324-L360","documentation":"The doctor's _probe_provider makes a tiny LLM call (max_tokens=64, max_retries=0, no image fallback) and raises RuntimeError when the response text is empty after stripping. It distinguishes 'provider reachable' from 'provider returned nothing', which often indicates auth/quota/model issues the API did not surface as an error status.","triggerScenarios":"run_diagnostics(online=True) probing a provider whose endpoint returns 200 with empty content, or a reasoning model that spends all 64 tokens invisibly leaving no visible text.","commonSituations":"Misconfigured base_url pointing at a gateway that swallows content; quota exhausted so the backend returns empty bodies; reasoning models consuming the tiny token budget before emitting text.","solutions":["Increase max_tokens for the probe (reasoning models can burn 64 tokens with no visible output)","Verify provider config — API key, base_url, model name — in Settings and re-run diagnostics","Bypass the gateway: test the same key with curl to confirm non-empty completions"],"exampleFix":"# before\nresp = await client.chat.completions.create(..., max_tokens=64)\n# after\nresp = await client.chat.completions.create(..., max_tokens=512)\nif not (resp.text or \"\").strip():\n    raise RuntimeError(\"empty response — check key/quota/base_url\")","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    await run_diagnostics(online=True)\nexcept RuntimeError as e:\n    if \"empty response\" in str(e):\n        report(\"provider reachable but returned empty output — check key/quota/model\")\n    raise","preventionTips":["Probe with enough max_tokens for reasoning models (>=512)","Verify base_url/key with curl before diagnosing app-level issues","Treat empty-but-200 responses as config smells, not successes"],"tags":["llm","diagnostics","empty-response","provider"],"backgroundTag":"llm-empty-response","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}