apache/answer · error

ReadableStream not supported

Error message

ReadableStream not supported

What it means

requestAi throws this when the browser's fetch Response body is not a ReadableStream, i.e. response.body?.getReader() returns undefined. The AI streaming feature depends on the Streams API to consume the response incrementally.

Source

Thrown at ui/src/utils/requestAi.ts:224

      method: 'POST',
      signal: combinedSignal,
      headers: {
        Authorization: token,
        'Accept-Language': lang,
        'Content-Type': 'application/json',
        ...options.headers,
      },
    });

    // unified error handling (based on request.ts logic)
    if (!response.ok) {
      await handleHttpError(response, options);
      return;
    }

    const reader = response.body?.getReader();
    if (!reader) {
      throw new Error('ReadableStream not supported');
    }

    // store the current reader so it can be cancelled later
    requestState.currentReader = reader;

    const decoder = new TextDecoder();
    let buffer = '';

    const processStream = async (): Promise<void> => {
      try {
        const { value, done } = await reader.read();

        if (done) {
          options.onComplete?.();
          requestState.isProcessing = false;
          requestState.currentReader = null;
          return;
        }

View on GitHub (pinned to 3b9f137061)

Solutions

  1. Upgrade to a browser that supports ReadableStream (all modern evergreen browsers, Safari 10.1+).
  2. Check that fetch is native, not polyfilled; remove or upgrade the fetch polyfill for this call path.
  3. Serve the app over HTTPS/modern context if targeting browsers that gate streams on secure contexts.
  4. Add an explicit feature check before calling requestAi and fall back to a non-streaming request path.

Example fix

// before
const reader = response.body?.getReader();
if (!reader) {
  throw new Error('ReadableStream not supported');
}
// after
if (typeof response.body?.getReader !== 'function') {
  const text = await response.text(); // non-streaming fallback
  return handleFullText(text);
}
const reader = response.body.getReader();
Defensive patterns

Strategy: type-guard

Validate before calling

const supportsStreams = typeof Response !== 'undefined' && new Response().body?.getReader instanceof Function;

Type guard

function hasReadableStream(res: Response): res is Response & { body: ReadableStream } {
  return !!res.body && typeof res.body.getReader === 'function';
}

Try / catch

try {
  await requestAi(params);
} catch (e) {
  if (e instanceof Error && e.message === 'ReadableStream not supported') {
    await requestAiNonStreaming(params); // fallback path
  } else throw e;
}

Prevention

When it happens

Trigger: Calling requestAi (streaming mode) in an environment where Response.body is null or lacks getReader(): old browsers without ReadableStream support, non-HTTPS contexts in some browsers, or certain polyfilled/undici-like fetch implementations that return null bodies.

Common situations: Running the app in legacy browsers (older Safari/IE-based webviews), embedding the UI in an old WebView, using a fetch polyfill that strips the body stream, or service-worker/proxy layers that buffer the response so body.getReader is unavailable.


AI-assisted analysis of apache/answer@3b9f137061 (2026-09-05). Data as JSON: /api/errors/506645d6ff0c4ab5. Report an issue: GitHub.