apache/superset · error
Response body is not available for streaming
Error message
Response body is not available for streaming
What it means
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.
Source
Thrown at superset-frontend/src/components/StreamingExportModal/useStreamingExport.ts:241
payload,
filename,
exportType,
exportSource,
expectedRows,
abortControllerRef.current.signal,
);
// Guard: ensure URL has app root prefix for subdirectory deployments
const prefixedUrl = ensureUrlPrefix(url);
const response = await fetch(prefixedUrl, fetchOptions);
if (!response.ok) {
throw new Error(
`Export failed: ${response.status} ${response.statusText}`,
);
}
if (!response.body) {
throw new Error('Response body is not available for streaming');
}
const contentDisposition = response.headers.get('Content-Disposition');
const defaultFilename = `export.${exportType}`;
let serverFilename = defaultFilename;
if (contentDisposition) {
const filenameMatch =
contentDisposition.match(/filename="?([^"]+)"?/);
if (filenameMatch && filenameMatch[1]) {
serverFilename = filenameMatch[1];
}
}
const reader = response.body.getReader();
const chunks: Uint8Array[] = [];
let receivedLength = 0;
let rowsProcessed = 0;View on GitHub (pinned to f4587218dd)
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(...).
Example fix
// before (interceptor)
return new Response(await cached.text()); // body may be null
// after (interceptor)
return new Response(new ReadableStream({ start(c) { c.enqueue(bytes); c.close(); } })); Defensive patterns
Strategy: type-guard
Validate before calling
const response = await fetch(url, opts);
if (!response.body) {
// fall back to blob download instead of streaming
const blob = await response.blob();
saveAs(blob, filename);
} Type guard
const isStreamableResponse = (r: Response): boolean => r.body instanceof ReadableStream || typeof r.body?.getReader === 'function';
Try / catch
try { streamExport(response); } catch (e) { if (e.message === 'Response body is not available for streaming') downloadViaBlob(response); else throw e; } Prevention
- Whitelist export routes in service workers
- Keep a non-streaming blob fallback for environments without ReadableStream
- Set body on fetch mocks in tests
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Export failed: ${response.status} ${response.statusText}
- Dashboard not found.
- Chart has no valid query context saved.
- Unsupported chart data result format: {result_format}
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/5298a7ed0c20835a.
Report an issue: GitHub.