{"record":{"id":"5298a7ed0c20835a","repo":"apache/superset","slug":"response-body-is-not-available-for-streaming","errorCode":null,"errorMessage":"Response body is not available for streaming","messagePattern":"Response body is not available for streaming","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"superset-frontend/src/components/StreamingExportModal/useStreamingExport.ts","lineNumber":241,"sourceCode":"          payload,\n          filename,\n          exportType,\n          exportSource,\n          expectedRows,\n          abortControllerRef.current.signal,\n        );\n        // Guard: ensure URL has app root prefix for subdirectory deployments\n        const prefixedUrl = ensureUrlPrefix(url);\n        const response = await fetch(prefixedUrl, fetchOptions);\n\n        if (!response.ok) {\n          throw new Error(\n            `Export failed: ${response.status} ${response.statusText}`,\n          );\n        }\n\n        if (!response.body) {\n          throw new Error('Response body is not available for streaming');\n        }\n\n        const contentDisposition = response.headers.get('Content-Disposition');\n        const defaultFilename = `export.${exportType}`;\n        let serverFilename = defaultFilename;\n\n        if (contentDisposition) {\n          const filenameMatch =\n            contentDisposition.match(/filename=\"?([^\"]+)\"?/);\n          if (filenameMatch && filenameMatch[1]) {\n            serverFilename = filenameMatch[1];\n          }\n        }\n\n        const reader = response.body.getReader();\n        const chunks: Uint8Array[] = [];\n        let receivedLength = 0;\n        let rowsProcessed = 0;","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset-frontend/src/components/StreamingExportModal/useStreamingExport.ts#L223-L259","documentation":"Thrown by the streaming export hook when response.ok is true but response.body is null. The hook iterates response.body.getReader() to stream chunks and compute progress; a null body makes streaming impossible. null bodies occur when fetch is intercepted (some service workers, opaque no-cors responses) or in environments without ReadableStream support.","triggerScenarios":"An export fetch whose response exposes no ReadableStream: a service worker returning a synthetic Response (new Response(blob)) without a stream, a no-cors/opaque response, or an old browser/polyfill lacking response.body.","commonSituations":"PWA/service-worker wrappers around Superset synthesizing responses; corporate proxies that fully buffer and re-serve responses; outdated browser baselines; test environments using fetch mocks that forget to set body.","solutions":["Bypass/whitelist the Superset export routes in any service worker so the native streamed response passes through.","Verify browser support for ReadableStream and that no fetch polyfill strips body.","If interception is unavoidable, make the interceptor construct the Response with a real stream (e.g. new Response(stream)).","In fetch mocks/tests, provide body: new ReadableStream(...)."],"exampleFix":"// before (interceptor)\nreturn new Response(await cached.text()); // body may be null\n\n// after (interceptor)\nreturn new Response(new ReadableStream({ start(c) { c.enqueue(bytes); c.close(); } }));","handlingStrategy":"type-guard","validationCode":"const response = await fetch(url, opts);\nif (!response.body) {\n  // fall back to blob download instead of streaming\n  const blob = await response.blob();\n  saveAs(blob, filename);\n}","typeGuard":"const isStreamableResponse = (r: Response): boolean => r.body instanceof ReadableStream || typeof r.body?.getReader === 'function';","tryCatchPattern":"try { streamExport(response); } catch (e) { if (e.message === 'Response body is not available for streaming') downloadViaBlob(response); else throw e; }","preventionTips":["Whitelist export routes in service workers","Keep a non-streaming blob fallback for environments without ReadableStream","Set body on fetch mocks in tests"],"tags":["export","streaming","fetch-api","browser-support"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}