yikart/AiToEarn · error · Error

无法获取响应流

Error message

无法获取响应流

What it means

After the fetch succeeds in testSseFunc, it reads the SSE stream via response.body.getReader(). If response.body is null (no readable stream), it throws '无法获取响应流'. Per fetch spec the body can be null for certain responses (opaque no-cors responses, 204/304, or non-browser contexts lacking stream support).

Source

Thrown at project/aitoearn-electron/src/views/task/task.tsx:1041

        import.meta.env.VITE_APP_URL + '/tools/ai/article/html/sse',
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            content: '生成一个卡通人物介绍页 带有图片 小红书图文流光卡片样式',
          }),
        },
      );

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const reader = response.body?.getReader();
      if (!reader) {
        throw new Error('无法获取响应流');
      }

      let htmlString = '';
      let isCollectingHtml = false;
      let buffer = '';

      // 处理响应流
      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          console.log('流读取完成');
          setHtmlContent(htmlString); // 设置最终的 HTML 内容
          break;
        }

        // 将 Uint8Array 转换为文本
        const text = new TextDecoder().decode(value);
        buffer += text;

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Ensure the request is CORS-enabled (no opaque 'no-cors' mode) so response.body is a real stream
  2. Check response.status — 204/304 have no body; treat them separately
  3. Verify the server sends chunked/streaming (SSE) responses and no proxy buffers/strips them
  4. Fall back to non-streaming consumption (response.text()) when body is unavailable

Example fix

// before
const reader = response.body?.getReader();
if (!reader) {
  throw new Error('无法获取响应流');
}
// after
if (!response.body) {
  const text = await response.text(); // fallback: consume whole body
  handleNonStreamed(text);
  return;
}
const reader = response.body.getReader();
Defensive patterns

Strategy: type-guard

Validate before calling

const res = await fetch(url, init)
if (!res.ok) throw new Error(`HTTP ${res.status}`)
if (!res.body) throw new Error('no stream body') // check before streaming

Type guard

function hasReadableBody(r: Response): r is Response & { body: ReadableStream } {
  return r.body !== null
}

Try / catch

try {
  await testSseFunc()
} catch (e) {
  if (e.message === '无法获取响应流') {
    return fallbackToNonStreamingFetch(url, init) // e.g. response.text()
  }
  throw e
}

Prevention

When it happens

Trigger: Calling testSseFunc with mode:'no-cors' (opaque response ⇒ body null), the server returning 204/304, or a runtime where ReadableStream response bodies are unavailable.

Common situations: Copied the fetch pattern from a CORS-enabled context into a no-cors request; a proxy/CDN strips the body; older Electron/Chromium build with streaming disabled for the response type.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/881cabb609145baf. Report an issue: GitHub.