{"record":{"id":"e6d827a4c5197e63","repo":"unslothai/unsloth","slug":"chatgpt-stream-ended-before-completion","errorCode":null,"errorMessage":"ChatGPT stream ended before completion.","messagePattern":"ChatGPT stream ended before completion\\.","errorType":"exception","errorClass":"CodexTransportError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/inference/openai_codex_client.py","lineNumber":721,"sourceCode":"                        elif kind in (\"response.failed\", \"error\"):\n                            error = (\n                                event.get(\"error\")\n                                or (event.get(\"response\") or {}).get(\"error\")\n                                or {}\n                            )\n                            code = error.get(\"code\") if isinstance(error, dict) else None\n                            raise CodexTransportError(\n                                f\"ChatGPT Codex generation failed{f' ({code})' if code else ''}.\"\n                            )\n                except httpx.HTTPError:\n                    if cancel_event is not None and cancel_event.is_set():\n                        return\n                    raise\n        finally:\n            if cancel_task is not None:\n                cancel_task.cancel()\n        if not emitted_terminal and not (cancel_event is not None and cancel_event.is_set()):\n            raise CodexTransportError(\"ChatGPT stream ended before completion.\")\n","sourceCodeStart":703,"sourceCodeEnd":722,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/openai_codex_client.py#L703-L722","documentation":"After the SSE loop finished, no terminal success event (response.completed with usage) was emitted and the stream was not user-cancelled — the connection closed mid-generation without a proper terminator. This guards against silently truncated answers: partial text was yielded but completion never confirmed.","triggerScenarios":"Upstream or an intermediary closes the TCP stream after deltas but before response.completed; emitted_terminal stays False and cancel_event is unset, so the guard raises. Any dropped connection during generation.","commonSituations":"Idle-timeout or byte-timeout on a proxy/load balancer cutting long streams; mobile/flaky networks; upstream connection resets; keep-alive gaps exceeding intermediary limits.","solutions":["Retry the generation — the request is idempotent at the prompt level and most truncations are transient","Raise stream/read timeouts and proxy idle timeouts for long generations","If using tool deltas, keep the stream active; avoid long silent gaps that trigger LB idle kills"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    collect(stream)\nexcept CodexTransportError as exc:\n    if 'ended before completion' in str(exc):\n        return await retry_generation_once(request)  # truncated: discard partials\n    raise","preventionTips":["Raise idle/read timeouts on proxies and the httpx client for long streams","Discard partial text on truncation — never persist it as a complete answer","Retry truncated generations once automatically; flag repeat truncation as a network issue"],"tags":["sse","streaming","truncation","codex","network"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}