{"record":{"id":"277f88380167fecc","repo":"yikart/AiToEarn","slug":"http-response-status-277f88","errorCode":null,"errorMessage":"HTTP ${response.status}","messagePattern":"HTTP \\$\\{response\\.status\\}","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"project/aitoearn-web/src/api/ai/ai.api.ts","lineNumber":136,"sourceCode":"        openWhenHidden: true,\n\n        // 当连接打开时\n        async onopen(response) {\n          if (response.ok) {\n            return // 一切正常，继续处理消息\n          }\n\n          // 处理错误响应\n          if (response.status >= 400 && response.status < 500 && response.status !== 429) {\n            // 客户端错误，不重试\n            const errorText = await response.text()\n            console.error('[SSE] Client error:', response.status, errorText)\n            throw new Error(`HTTP ${response.status}: ${errorText}`)\n          }\n          else {\n            // 服务器错误或其他问题，不自动重试，直接抛出错误\n            console.error('[SSE] Server error:', response.status)\n            throw new Error(`HTTP ${response.status}`)\n          }\n        },\n\n        // 当收到消息时\n        onmessage(event) {\n          // 如果已完成，忽略后续消息\n          if (isCompleted) {\n            return\n          }\n\n          // 如果没有数据，跳过\n          if (!event.data) {\n            return\n          }\n\n          try {\n            const data = JSON.parse(event.data)\n","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-web/src/api/ai/ai.api.ts#L118-L154","documentation":" thrown by the SSE onopen handler in ai.api.ts for any status not in the 4xx-client-error band (or 429) — i.e. 5xx server errors or abnormal statuses. Unlike the client-error branch it contains no response body, only the numeric status. Signals the backend/stream gateway failed rather than the request being malformed.","triggerScenarios":"Opening an AI SSE stream while the backend returns 500/502/503/504 — e.g. upstream LLM provider outage, backend crash, gateway timeout, or service being restarted.","commonSituations":"LLM provider quota/outage causing backend 5xx; deployment or rolling restart mid-stream; nginx/gateway timeout (502/504) on long-lived SSE connections; overloaded AI service.","solutions":["Check backend logs at the corresponding timestamp for the 5xx root cause.","Retry the request after a short delay — server errors are often transient (and 429 is already treated as retryable).","Increase gateway/proxy read timeouts for SSE endpoints to avoid 504 on long streams.","Add status-based user messaging in the UI ('服务暂时不可用，请稍后重试')."],"exampleFix":"// before\nthrow new Error(`HTTP ${response.status}`)\n// after\nif (response.status >= 500) return retryWithBackoff() // caller-level retry\nthrow new Error(`HTTP ${response.status}`)","handlingStrategy":"retry","validationCode":"// probe backend health before opening the stream\nconst health = await fetch('/api/health').then(r => r.ok).catch(() => false)\nif (!health) throw new Error('AI 服务暂不可用')","typeGuard":"function isServerHttpError(e: unknown): e is Error {\n  return e instanceof Error && /^HTTP 5\\d\\d$/.test(e.message)\n}","tryCatchPattern":"try {\n  await openAiSseStream(params)\n}\ncatch (e) {\n  if (e instanceof Error && /^HTTP 5\\d\\d$/.test(e.message)) {\n    await retryWithBackoff(() => openAiSseStream(params), { attempts: 3 })\n  }\n  else throw e\n}","preventionTips":["Implement exponential-backoff retry for 5xx and 429 on stream open.","Increase proxy read timeouts (proxy_read_timeout) for SSE routes.","Add backend health checks before deploying stream-dependent UI.","Alert on SSE 5xx rates to catch provider outages early."],"tags":["sse","server-error","streaming","network"],"backgroundTag":"sse-connection-failed","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}