datawhalechina/hello-agents · error

msg

Error message

msg

What it means

In StockSage's StockAnalysis.vue the code throws `new Error(msg)` when the analysis stream request responds non-OK. msg is resolved in priority order: JSON body's `message` field, else raw body text, else statusText — so the literal 'msg' in the error listing is just the variable name; the real message is whatever the server sent. This is the single rejection point for the Buffett-analysis streaming POST.

Source

Thrown at Co-creation-projects/lcyting-StockSage-agent/frontend/src/views/StockAnalysis.vue:1050

      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/x-ndjson',
      },
      body: JSON.stringify({
        stock_code: stockCode.value.trim(),
        stock_name: (stockName.value || '').trim(),
      }),
    })
    if (!res.ok) {
      const t = await res.text()
      let msg = t || res.statusText
      try {
        const j = JSON.parse(t)
        if (j.message) msg = j.message
      } catch {
        /* ignore */
      }
      throw new Error(msg)
    }
    const reader = res.body?.getReader()
    if (!reader) throw new Error('无法读取响应流')

    const dec = new TextDecoder()
    let buf = ''
    let streamError = null
    let streamFinished = false

    while (true) {
      const { done: readerDone, value } = await reader.read()
      if (value) buf += dec.decode(value, { stream: true })

      let nl
      while ((nl = buf.indexOf('\n')) >= 0) {
        const line = buf.slice(0, nl).trim()
        buf = buf.slice(nl + 1)
        if (!line) continue

View on GitHub (pinned to 606a07d341)

Solutions

  1. Read the thrown message — when the backend sent {message: ...} it names the exact server-side failure; statusText-only means an empty body (check nginx/gateway).
  2. Validate stockName is non-empty before invoking the stream (the code trims but the caller may skip checking).
  3. Confirm the proxy config forwards the analysis endpoint to the backend port in dev and prod.
  4. Check backend logs when the message references model/API errors (keys, quotas).
Defensive patterns

Strategy: try-catch

Validate before calling

const name = (stockName.value || '').trim();
if (!name) {
  ElMessage.warning('请输入股票名称');
  return;
}

Type guard

function hasErrorMessageFrame(t: string): { message?: string } | null {
  try {
    const j = JSON.parse(t);
    return typeof j === 'object' && j !== null && 'message' in j ? j : null;
  } catch {
    return null;
  }
}

Try / catch

try {
  await runAnalysisStream(stockName.value.trim());
} catch (err) {
  const m = (err as Error).message;
  if (/404|Not Found/i.test(m)) hintApiUrl();
  else if (/422|validation/i.test(m)) hintStockName();
  else showError(m || '分析请求失败');
}

Prevention

When it happens

Trigger: POST to the stock-analysis stream endpoint with {stock_name, ...} returns non-2xx: 404 wrong URL, 422 empty/unknown stock_name (it is trimmed from an input), 500 when the LLM/stream pipeline fails, 502/503 when the gateway is down. The JSON.parse fallback exists because the backend sometimes returns an HTML/plain error page.

Common situations: stockName left blank after trim → backend validation error; backend not running or Vite dev proxy missing for the API path; upstream LLM API key invalid so the handler 500s with {message: ...}; HTML error pages from nginx breaking naive error rendering.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/8f51a18385f60db1. Report an issue: GitHub.