{"record":{"id":"6d363dd2ea25a0ca","repo":"unslothai/unsloth","slug":"response-interrupted-the-connection-dropped-befor","errorCode":null,"errorMessage":"Response interrupted: the connection dropped before the model finished. Use Retry to regenerate.","messagePattern":"Response interrupted: the connection dropped before the model finished\\. Use Retry to regenerate\\.","errorType":"exception","errorClass":"StreamInterruptedError","httpStatus":null,"severity":"error","filePath":"studio/frontend/src/features/chat/api/chat-api.ts","lineNumber":1346,"sourceCode":"  let sawReasoningContent = false;\n\n  const throwIfReasoningOnlyLength = () => {\n    if (\n      terminalFinishReason === \"length\" &&\n      sawReasoningContent &&\n      !sawAssistantContent\n    ) {\n      throw new GenerationLengthError();\n    }\n  };\n\n  try {\n    while (true) {\n      const { done, value } = await reader.read();\n      if (done) {\n        completed = true;\n        if (!sawTerminalSignal) {\n          throw new StreamInterruptedError();\n        }\n        throwIfReasoningOnlyLength();\n        break;\n      }\n\n      buffer += decoder.decode(value, { stream: true });\n\n      let separatorIndex = buffer.search(/\\r?\\n\\r?\\n/);\n      while (separatorIndex >= 0) {\n        const rawEvent = buffer.slice(0, separatorIndex);\n        const separatorLength = buffer[separatorIndex] === \"\\r\" ? 4 : 2;\n        buffer = buffer.slice(separatorIndex + separatorLength);\n\n        const dataLines = parseSseEvent(rawEvent);\n        if (dataLines.length === 0) {\n          separatorIndex = buffer.search(/\\r?\\n\\r?\\n/);\n          continue;\n        }","sourceCodeStart":1328,"sourceCodeEnd":1364,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/frontend/src/features/chat/api/chat-api.ts#L1328-L1364","documentation":"StreamInterruptedError is thrown when the SSE reader hits EOF (done === true) without ever seeing a terminal signal — neither the [DONE] sentinel nor a chunk with a finish_reason. The connection closed mid-generation, so the partial transcript is incomplete. The message directs the user to Retry to regenerate.","triggerScenarios":"Network drop, proxy timeout, server crash, or load-balancer idle kill between chunks: reader.read() resolves done=true with sawTerminalSignal still false.","commonSituations":"Long generations exceeding proxy/gateway timeouts (nginx proxy_read_timeout, ALB idle timeout); flaky mobile connections; inference server OOM or restart mid-stream; VPN reconnects.","solutions":["Retry the generation — the UI Retry action re-issues the request.","Raise intermediary timeouts (proxy_read_timeout, LB idle timeout) for /v1/chat/completions.","If it reproduces consistently at the same elapsed time, find and raise the timeout that matches that duration.","Check inference-server logs for OOM/crash mid-generation."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"export function isStreamInterruptedError(e: unknown): e is StreamInterruptedError {\n  return e instanceof StreamInterruptedError;\n}","tryCatchPattern":"try { for await (const c of stream) render(c); }\ncatch (e) {\n  if (isStreamInterruptedError(e) && attempt < 2) { await backoff(attempt); return regenerate(); }\n  throw e;\n}","preventionTips":["Raise proxy/LB idle timeouts above worst-case generation time.","Keep a Retry affordance on partial transcripts so users self-heal.","Persist partial output before discarding, so a drop is not data loss."],"tags":["streaming","network","timeout","sse"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}