{"record":{"id":"53b2133d0e2c4aa4","repo":"Wei-Shaw/sub2api","slug":"no-response-body","errorCode":null,"errorMessage":"No response body","messagePattern":"No response body","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/components/account/AccountTestModal.vue","lineNumber":445,"sourceCode":"      headers: {\n        Authorization: `Bearer ${localStorage.getItem('auth_token')}`,\n        'Content-Type': 'application/json'\n      },\n      body: JSON.stringify({\n        model_id: selectedModelId.value,\n        prompt: supportsImageTest.value ? testPrompt.value.trim() : '',\n        mode: isOpenAIAccount.value ? testMode.value : 'default'\n      }),\n      signal: abortController.signal\n    })\n\n    if (!response.ok) {\n      throw new Error(`HTTP error! status: ${response.status}`)\n    }\n\n    const reader = response.body?.getReader()\n    if (!reader) {\n      throw new Error('No response body')\n    }\n\n    const decoder = new TextDecoder()\n    let buffer = ''\n\n    while (true) {\n      const { done, value } = await reader.read()\n      if (done) break\n\n      buffer += decoder.decode(value, { stream: true })\n      const lines = buffer.split('\\n')\n      buffer = lines.pop() || ''\n\n      for (const line of lines) {\n        if (line.startsWith('data: ')) {\n          const jsonStr = line.slice(6).trim()\n          if (jsonStr) {\n            try {","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/Wei-Shaw/sub2api/blob/073e92d17178a1ccdb0a27017f572f10c9c7ab62/frontend/src/components/account/AccountTestModal.vue#L427-L463","documentation":"In frontend/src/components/account/AccountTestModal.vue:445, after response.ok passes, the code calls response.body?.getReader(). response.body is null when the response has no body (204/304) or when the browser does not expose a ReadableStream body (very old browsers, some WebViews). Since this endpoint streams NDJSON, a missing body means streaming is impossible, so the code throws 'No response body'.","triggerScenarios":"The test endpoint returns 204/304 or an empty 200; a proxy (nginx buffering, Cloudflare, corporate proxy) strips the streamed body; the browser is old (pre-2017 Safari/Chrome) lacking fetch streaming; or the server responded and closed without a body via a misconfigured handler.","commonSituations":"Reverse proxy configured without chunked-transfer support or with proxy_buffering that collapses the stream; server handler returning Response with no body on a success path; WebView-based mobile browsers.","solutions":["Confirm the endpoint actually returns a chunked/streamed body (curl -N test).","Disable proxy buffering for this route (nginx: proxy_buffering off; X-Accel-Buffering: no header).","Add a capability check for response.body before fetch when targeting old browsers, or switch to XHR-based streaming.","Include response headers in the error (Content-Length, Content-Type) to diagnose empty responses."],"exampleFix":"// before\nconst reader = response.body?.getReader()\nif (!reader) {\n  throw new Error('No response body')\n}\n\n// after\nconst reader = response.body?.getReader()\nif (!reader) {\n  const fallback = await response.text().catch(() => '')\n  if (fallback) { handleNonStreamedPayload(fallback); return }\n  throw new Error(`No response body (status ${response.status})`)\n}","handlingStrategy":"validation","validationCode":"if (typeof ReadableStream === 'undefined' || !Response.prototype.body) {\n  showUnsupportedBrowserNotice(); // before starting the streaming request\n}","typeGuard":null,"tryCatchPattern":"try { await runStream(); }\ncatch (e) {\n  if (e.message === 'No response body') {\n    showError('Streaming unavailable — check proxy or browser'); return;\n  }\n  throw e;\n}","preventionTips":["Disable proxy buffering (proxy_buffering off / X-Accel-Buffering: no) on streaming routes","Feature-detect response streaming before offering the test feature","Fall back to response.text() when body is missing so non-streamed payloads still work"],"tags":["streaming","fetch-api","proxy","browser-support","frontend"],"backgroundTag":null,"analyzedSha":"073e92d17178a1ccdb0a27017f572f10c9c7ab62","analyzedAt":"2026-08-15T14:33:00.750Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}