{"record":{"id":"267d129e8787c64c","repo":"flipped-aurora/gin-vue-admin","slug":"llm-stream-failed","errorCode":null,"errorMessage":"LLM stream failed","messagePattern":"LLM stream failed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/src/api/autoCode.js","lineNumber":121,"sourceCode":"\n  const handleSSEEvent = (event) => {\n    const eventName = firstText(event.event, event.type) || 'message'\n    const text = pickStreamText(event)\n\n    if (event && typeof event === 'object') {\n      state.lastPayload = event\n      state.conversationId =\n        firstText(event.conversation_id, event.conversationId) ||\n        state.conversationId\n      state.messageId =\n        firstText(event.message_id, event.messageId) || state.messageId\n    }\n    if (text) {\n      state.answerText = mergeStreamText(state.answerText, text)\n    }\n\n    if (eventName === 'error' || event?.error || event?.status === 'error') {\n      throw new Error(\n        firstText(event?.message, event?.msg, event?.error) ||\n          'LLM stream failed'\n      )\n    }\n\n    options.onMessage?.({\n      event: eventName,\n      data: event,\n      rawData: JSON.stringify(event),\n      text: state.answerText,\n      conversationId: state.conversationId,\n      messageId: state.messageId\n    })\n  }\n\n  try {\n    const fetchUrl = `${import.meta.env.VITE_BASE_API || ''}${url}`\n    console.debug('[SSE] fetch →', fetchUrl)","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/web/src/api/autoCode.js#L103-L139","documentation":"handleSSEEvent parses Server-Sent Events coming from the LLM auto-code stream endpoint. When the SSE event is an error event (event name 'error', an error field, or status === 'error'), it throws so the caller aborts the stream and surfaces the upstream failure message.","triggerScenarios":"streamLLMRequest receives an SSE event where eventName === 'error', event.error is set, or event.status === 'error', and the payload carries no usable message/msg/error text so the fallback 'LLM stream failed' is used.","commonSituations":"Upstream LLM provider returns an in-stream error (quota exhausted, invalid API key, model unavailable); proxy relays the error without a message field; backend endpoint crashes mid-stream and emits a bare error event.","solutions":["Check the SSE payload from the backend for message/msg/error fields and populate one so the client shows a meaningful message","Verify the upstream LLM API key, quota and model name on the server","Check server logs for the mid-stream failure that produced the error event","Add retry logic in streamLLMRequest for transient upstream errors"],"exampleFix":"// before\nthrow new Error(firstText(event?.message, event?.msg, event?.error) || 'LLM stream failed')\n// after\nthrow new Error(firstText(event?.message, event?.msg, event?.error) || `LLM stream failed (event: ${eventName || 'unnamed'})`)","handlingStrategy":"try-catch","validationCode":"// before streaming, check feature flag / endpoint health\nconst res = await fetch('/api/llm/health').catch(() => null)\nif (!res || !res.ok) throw new Error('LLM service unavailable, aborting stream')","typeGuard":"function isSSEErrorEvent(ev) {\n  return ev?.name === 'error' || Boolean(ev?.error) || ev?.status === 'error'\n}","tryCatchPattern":"try {\n  await streamLLMRequest(url, options)\n} catch (e) {\n  if (e.message === 'LLM stream failed' || isSSEErrorEvent(lastEvent)) {\n    ElMessage.error(e.message || '生成中断，请重试')\n  } else {\n    throw e\n  }\n}","preventionTips":["Always send a message/msg field in backend error SSE events","Check LLM provider key/quota before long streams","Show partial answerText to the user when the stream errors mid-way"],"tags":["sse","streaming","llm","frontend"],"backgroundTag":"sse-stream-error-event","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}