{"record":{"id":"aefba65d69ee7371","repo":"iflytek/astron-agent","slug":"failed-to-establish-sse-connection-use-document-page","errorCode":null,"errorMessage":"Failed to establish SSE connection","messagePattern":"Failed to establish SSE connection","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"console/frontend/src/pages/resource-management/knowledge-detail/document-page/hooks/use-document-page.tsx","lineNumber":188,"sourceCode":"      // 获取访问令牌\n      const accessToken = localStorage.getItem('accessToken');\n      const headers: Record<string, string> = {};\n      if (accessToken) {\n        headers['Authorization'] = `Bearer ${accessToken}`;\n      }\n\n      await fetchEventSource(\n        `${getFixedUrl('/file/search-file')}?fileName=${encodeURIComponent(\n          searchValue\n        )}&repoId=${repoId}&pid=${parentId}&tag=${tag}`,\n        {\n          signal: controllerRef?.current?.signal,\n          headers,\n          async onopen(response) {\n            if (response.ok) {\n              setLoading(false);\n            } else {\n              throw new Error(`Failed to establish SSE connection`);\n            }\n          },\n          onmessage(event) {\n            if (event.data === 'bye') {\n              controllerRef.current?.abort();\n              controllerRef.current = null;\n              return;\n            }\n            const item = JSON.parse(event.data);\n            item.type = fileType(item);\n            const regexPattern = new RegExp(searchValue, 'gi');\n            item.name = item.name.replaceAll(\n              regexPattern,\n              '<span style=\"color:#6356EA;font-weight:600;display:inline-block;padding:4px 0px;background:#dee2f9\">$&</span>'\n            );\n\n            setSearchData(resultList => [...resultList, item]);\n          },","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/frontend/src/pages/resource-management/knowledge-detail/document-page/hooks/use-document-page.tsx#L170-L206","documentation":"The document page uses an SSE client (fetch-event-source style) whose `onopen` callback throws 'Failed to establish SSE connection' whenever the HTTP response is not ok (response.ok false, i.e. status outside 200-299). The library surfaces this thrown error through the returned promise, so the caller's catch handles a failed EventSource handshake.","triggerScenarios":"The SSE endpoint returns 401/403 (expired token in `headers`), 404 (wrong document/conversation URL), 500 from the backend, or a gateway 502/504 — any non-ok status triggers the throw inside onopen.","commonSituations":"Session token expired mid-use; auth header not attached; backend service down behind nginx; CORS preflight failing so fetch gets opaque/failed response; proxy timeout on long-lived SSE endpoints.","solutions":["Inspect response.status in onopen and throw a message including the status code for diagnosis.","Refresh/re-obtain the auth token and retry the connection with updated headers.","Verify the SSE endpoint URL and that the backend service and gateway route are healthy.","Add abort + retry with backoff for transient 5xx failures (the signal is already wired via controllerRef)."],"exampleFix":"// before\nasync onopen(response) {\n  if (response.ok) {\n    setLoading(false);\n  } else {\n    throw new Error(`Failed to establish SSE connection`);\n  }\n}\n\n// after\nasync onopen(response) {\n  if (response.ok) {\n    setLoading(false);\n    return;\n  }\n  const body = await response.text().catch(() => '');\n  throw new Error(`SSE connection failed: ${response.status} ${body.slice(0, 200)}`);\n}","handlingStrategy":"retry","validationCode":"const res = await fetch(sseUrl, { method: 'HEAD', headers });\nif (!res.ok) {\n  console.error('SSE endpoint unhealthy', res.status);\n  return; // or refresh token first\n}","typeGuard":"function isOkResponse(r: Response): boolean {\n  return r.status >= 200 && r.status < 300;\n}","tryCatchPattern":"try {\n  await fetchEventSource(url, { onopen, ...opts });\n} catch (e) {\n  if (String(e).includes('Failed to establish SSE connection')) {\n    await refreshToken();\n    scheduleRetryWithBackoff();\n  }\n  setLoading(false);\n}","preventionTips":["Refresh auth tokens proactively before opening long-lived SSE connections.","Log response.status in onopen for actionable diagnostics.","Implement retry with exponential backoff for transient 5xx/502/504.","Monitor gateway timeouts and tune proxy read timeouts for long SSE streams."],"tags":["sse","network","http","streaming"],"backgroundTag":"http-error-response","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}