{"record":{"id":"adeeef400a8e6e5e","repo":"datawhalechina/hello-agents","slug":"response-status","errorCode":null,"errorMessage":"研究请求失败，状态码：${response.status}","messagePattern":"研究请求失败，状态码：(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"Co-creation-projects/JJason-DeepCastAgent/frontend/src/services/api.ts","lineNumber":45,"sourceCode":"\nexport async function runResearchStream(\n  payload: ResearchRequest,\n  onEvent: (event: ResearchStreamEvent) => void,\n  options: StreamOptions = {}\n): Promise<void> {\n  const response = await fetch(`${baseURL}/research/stream`, {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application/json\",\n      Accept: \"text/event-stream\"\n    },\n    body: JSON.stringify(payload),\n    signal: options.signal\n  });\n\n  if (!response.ok) {\n    const errorText = await response.text().catch(() => \"\");\n    throw new Error(\n      errorText || `研究请求失败，状态码：${response.status}`\n    );\n  }\n\n  const body = response.body;\n  if (!body) {\n    throw new Error(\"浏览器不支持流式响应，无法获取研究进度\");\n  }\n\n  const reader = body.getReader();\n  const decoder = new TextDecoder(\"utf-8\");\n  let buffer = \"\";\n\n  while (true) {\n    const { value, done } = await reader.read();\n    buffer += decoder.decode(value || new Uint8Array(), { stream: !done });\n\n    let boundary = buffer.indexOf(\"\\n\\n\");","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/JJason-DeepCastAgent/frontend/src/services/api.ts#L27-L63","documentation":"Thrown by the SSE streaming client for POST /research/stream when the HTTP response status is not OK. It first tries to read the body as text and use it as the message; only when the body is unreadable/empty does it throw the template literal containing the status code. So seeing this exact templated message means the server returned an error with an empty or unreadable body.","triggerScenarios":"POST to ${baseURL}/research/stream returning 422 (payload validation failed), 401, 500 from the agent backend, or 502/504 from a reverse proxy with an empty body. Also happens when baseURL points to the wrong host and an edge returns a bare error status.","commonSituations":"Payload shape mismatch with the backend schema (missing required fields like query/topic), long-running research task killed by proxy idle timeout, backend not started, wrong vite proxy config for the /research path in dev.","solutions":["Reproduce with curl -i -X POST ${baseURL}/research/stream -H 'Content-Type: application/json' -d '<payload>' to see the real status and body","If 422, log the request payload and compare against the backend Pydantic model for the endpoint","If 502/504 from a proxy, raise proxy read/idle timeouts because SSE streams hold the connection open","Confirm baseURL resolves (check vite proxy or absolute URL) and the backend service is up"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (!payload || typeof payload !== 'object') throw new Error('payload required');","typeGuard":"function isResearchPayload(p) { return typeof p === 'object' && p !== null && 'query' in p; }","tryCatchPattern":"try { const stream = await startResearchStream(payload); } catch (e) { showBanner(e.message); disableStreamUI(); }","preventionTips":["Contract-test the /research/stream schema on both sides","Log response.status alongside message","Keep proxy read timeouts above the longest research run"],"tags":["sse","streaming","http","fetch"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}