{"record":{"id":"e3440af8552bb448","repo":"datawhalechina/hello-agents","slug":"error-e3440a","errorCode":null,"errorMessage":"生成失败","messagePattern":"生成失败","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/lcyting-StockSage-agent/frontend/src/views/StockAnalysis.vue","lineNumber":1085,"sourceCode":"        buf = buf.slice(nl + 1)\n        if (!line) continue\n        let obj\n        try {\n          obj = JSON.parse(line)\n        } catch {\n          continue\n        }\n        const deltaPiece = obj.text ?? obj.content\n        if (obj.type === 'delta' && deltaPiece) {\n          buffettStreamRaw.value += deltaPiece\n        } else if (obj.type === 'error') {\n          streamError = obj.message || obj.content || '生成失败'\n        } else if (obj.type === 'done') {\n          streamFinished = true\n        }\n      }\n\n      if (streamError) throw new Error(streamError)\n      if (streamFinished || readerDone) break\n    }\n\n    const tail = buf.trim()\n    if (tail) {\n      try {\n        const obj = JSON.parse(tail)\n        if (obj.type === 'error') throw new Error(obj.message || obj.content || '生成失败')\n        const tailDelta = obj.text ?? obj.content\n        if (obj.type === 'delta' && tailDelta) buffettStreamRaw.value += tailDelta\n      } catch (e) {\n        if (!(e instanceof SyntaxError)) throw e\n      }\n    }\n\n    const md = buffettStreamRaw.value.trim()\n    buffettAiMarkdown.value = md\n    buffettStreamRaw.value = ''","sourceCodeStart":1067,"sourceCodeEnd":1103,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/lcyting-StockSage-agent/frontend/src/views/StockAnalysis.vue#L1067-L1103","documentation":"'生成失败' (generation failed) is the default message assigned in StockAnalysis.vue's stream loop when an NDJSON frame arrives with type:'error' but carries neither message nor content fields. The frame signals a server-side error mid-stream; the thrown Error surfaces it after the read loop exits. It only shows the literal '生成失败' when the server sent a bare error event with no detail.","triggerScenarios":"The analysis stream opens OK, deltas flow, then the server emits {type:'error'} (optionally with message/content) — LLM provider failure mid-generation, upstream timeout, token limit hit, or internal exception in the analysis pipeline. The default text appears specifically when the error frame is empty.","commonSituations":"LLM API rate-limit/key errors surfacing mid-stream; long analyses hitting provider timeouts; backend catching an exception and emitting a bare error frame without details.","solutions":["Check the backend's error-frame emitter — make it always include the exception message so this default never fires blind.","Read backend logs at the timestamp of the failed stream for the real exception.","If it's provider rate-limiting/quota, fix keys/limits upstream and retry the analysis.","For timeout-class failures, chunk the analysis request or increase server-side LLM timeouts."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isErrorFrame(obj: unknown): obj is { type: 'error'; message?: string; content?: string } {\n  return typeof obj === 'object' && obj !== null && (obj as { type?: unknown }).type === 'error';\n}","tryCatchPattern":"try {\n  await streamBuffettAnalysis();\n} catch (err) {\n  const m = (err as Error).message;\n  if (m === '生成失败') {\n    // bare error frame — check server logs; likely LLM provider fault\n    showError('生成失败：上游模型异常，请稍后重试');\n  } else {\n    showError(m);\n  }\n}","preventionTips":["Make the backend always attach message/content to error frames so the default text never fires blind.","Keep partial deltas rendered (buffettStreamRaw already accumulates) so users keep what arrived before the error.","Retry once on transient provider errors before surfacing the failure."],"tags":["streaming","ndjson","llm-error","mid-stream-failure","vue"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}