flipped-aurora/gin-vue-admin · error · Error

LLM stream failed

Error message

LLM stream failed

What it means

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.

Source

Thrown at web/src/api/autoCode.js:121

  const handleSSEEvent = (event) => {
    const eventName = firstText(event.event, event.type) || 'message'
    const text = pickStreamText(event)

    if (event && typeof event === 'object') {
      state.lastPayload = event
      state.conversationId =
        firstText(event.conversation_id, event.conversationId) ||
        state.conversationId
      state.messageId =
        firstText(event.message_id, event.messageId) || state.messageId
    }
    if (text) {
      state.answerText = mergeStreamText(state.answerText, text)
    }

    if (eventName === 'error' || event?.error || event?.status === 'error') {
      throw new Error(
        firstText(event?.message, event?.msg, event?.error) ||
          'LLM stream failed'
      )
    }

    options.onMessage?.({
      event: eventName,
      data: event,
      rawData: JSON.stringify(event),
      text: state.answerText,
      conversationId: state.conversationId,
      messageId: state.messageId
    })
  }

  try {
    const fetchUrl = `${import.meta.env.VITE_BASE_API || ''}${url}`
    console.debug('[SSE] fetch →', fetchUrl)

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Check the SSE payload from the backend for message/msg/error fields and populate one so the client shows a meaningful message
  2. Verify the upstream LLM API key, quota and model name on the server
  3. Check server logs for the mid-stream failure that produced the error event
  4. Add retry logic in streamLLMRequest for transient upstream errors

Example fix

// before
throw new Error(firstText(event?.message, event?.msg, event?.error) || 'LLM stream failed')
// after
throw new Error(firstText(event?.message, event?.msg, event?.error) || `LLM stream failed (event: ${eventName || 'unnamed'})`)
Defensive patterns

Strategy: try-catch

Validate before calling

// before streaming, check feature flag / endpoint health
const res = await fetch('/api/llm/health').catch(() => null)
if (!res || !res.ok) throw new Error('LLM service unavailable, aborting stream')

Type guard

function isSSEErrorEvent(ev) {
  return ev?.name === 'error' || Boolean(ev?.error) || ev?.status === 'error'
}

Try / catch

try {
  await streamLLMRequest(url, options)
} catch (e) {
  if (e.message === 'LLM stream failed' || isSSEErrorEvent(lastEvent)) {
    ElMessage.error(e.message || '生成中断,请重试')
  } else {
    throw e
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/267d129e8787c64c. Report an issue: GitHub.