datawhalechina/hello-agents · error · Error
无法读取响应流
Error message
无法读取响应流
What it means
Thrown in StockAnalysis.vue when res.ok is true but res.body is null/undefined, so getReader() cannot be created — '无法读取响应流' (cannot read response stream). It guards the NDJSON-line streaming loop that follows; without a reader there is no way to consume the incremental analysis deltas. Unlike the !res.ok branch, this fires on a 200 response whose body was stripped or never provided.
Source
Thrown at Co-creation-projects/lcyting-StockSage-agent/frontend/src/views/StockAnalysis.vue:1053
},
body: JSON.stringify({
stock_code: stockCode.value.trim(),
stock_name: (stockName.value || '').trim(),
}),
})
if (!res.ok) {
const t = await res.text()
let msg = t || res.statusText
try {
const j = JSON.parse(t)
if (j.message) msg = j.message
} catch {
/* ignore */
}
throw new Error(msg)
}
const reader = res.body?.getReader()
if (!reader) throw new Error('无法读取响应流')
const dec = new TextDecoder()
let buf = ''
let streamError = null
let streamFinished = false
while (true) {
const { done: readerDone, value } = await reader.read()
if (value) buf += dec.decode(value, { stream: true })
let nl
while ((nl = buf.indexOf('\n')) >= 0) {
const line = buf.slice(0, nl).trim()
buf = buf.slice(nl + 1)
if (!line) continue
let obj
try {
obj = JSON.parse(line)View on GitHub (pinned to 606a07d341)
Solutions
- Log res.type — 'opaque' means a CORS/no-cors problem; fix the CORS headers or remove mode:'no-cors' from the fetch.
- Ensure the streaming route disables proxy buffering (nginx: proxy_buffering off; or X-Accel-Buffering: no response header).
- Verify the backend always returns a streaming body for this route, including on its 'immediate reply' path.
- Test in a modern browser to rule out missing resp.body support.
Defensive patterns
Strategy: type-guard
Validate before calling
const streamCapable = typeof ReadableStream !== 'undefined' && 'body' in Response.prototype;
if (!streamCapable) {
throw new Error('当前环境不支持流式响应');
}
// ensure fetch is same-origin/cors, never mode:'no-cors'
const resp = await fetch(url, { method: 'POST', headers, body }); // no mode:'no-cors' anywhere Type guard
function hasReadableBody(res: Response): res is Response & { body: NonNullable<Response['body']> } {
return res.body != null;
} Try / catch
const reader = hasReadableBody(res) ? res.body.getReader() : null;
if (!reader) {
if (res.type === 'opaque') showError('CORS 配置错误导致无法读取响应流');
else showError('当前浏览器不支持流式响应');
return;
} Prevention
- Never use mode:'no-cors' for streaming endpoints — opaque responses always have null body.
- Configure CORS headers properly on the backend instead of bypassing them.
- Disable proxy buffering on the streaming route so the body isn't closed early.
When it happens
Trigger: The stream endpoint returns 200 with no body: proxy or middleware that buffers and closes the stream, a backend handler that returns Response without a body on some path, an environment where fetch response streaming is unavailable (resp.body undefined in old browsers/WebViews), or an opaque response mode (mode:'opaque' from no-cors) which always has null body.
Common situations: CORS misconfiguration making the fetch fall into an opaque response; nginx buffering config for the streaming route; old in-app browsers lacking ReadableStream responses.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/6f4a8444a292bfa9.
Report an issue: GitHub.