datawhalechina/hello-agents · error

计划模式请求失败: ${resp.status}

Error message

计划模式请求失败: ${resp.status}

What it means

Thrown by buildPlan() in the AutoFlow frontend when the POST to /api/plan returns a non-2xx HTTP status. The fetch API does not throw on HTTP errors, so this manual check is the only signal that the plan-generation backend rejected the request. The message embeds only the numeric status code (e.g. '计划模式请求失败: 500' (plan mode request failed: 500)), which is the sole diagnostic available because the response body is discarded.

Source

Thrown at Co-creation-projects/usernamedadad-AutoFlow/frontend/src/services/api.js:11

const API_BASE = import.meta.env.VITE_API_BASE_URL || "";

export async function buildPlan(text, direction = "TD") {
  const resp = await fetch(`${API_BASE}/api/plan`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ text, direction }),
  });

  if (!resp.ok) {
    throw new Error(`计划模式请求失败: ${resp.status}`);
  }

  return resp.json();
}

function parseSSEChunk(buffer, onEvent) {
  const parts = buffer.split("\n\n");
  const remaining = parts.pop() || "";

  for (const block of parts) {
    const lines = block.split("\n");
    let eventType = "message";
    let dataLine = "";

    for (const line of lines) {
      if (line.startsWith("event:")) {
        eventType = line.slice(6).trim();
      }

View on GitHub (pinned to 606a07d341)

Solutions

  1. Check the status code in the message: 404 = wrong API_BASE or missing route, 422 = payload validation, 500 = backend crash (read backend logs), 502/503 = backend unreachable via proxy.
  2. Verify VITE_API_BASE_URL in frontend/.env(.local) and restart `npm run dev` (Vite only reads env at startup).
  3. Confirm the backend actually exposes POST /api/plan (check the backend router/main file) and that it is listening on the expected port.
  4. Open browser DevTools > Network to inspect the raw /api/plan response body, which this code throws away.
  5. Improve the throw to include the response body for future diagnosis (see exampleFix).

Example fix

// before
if (!resp.ok) {
  throw new Error(`计划模式请求失败: ${resp.status}`);
}

// after
if (!resp.ok) {
  const detail = await resp.text().catch(() => "");
  throw new Error(`计划模式请求失败: ${resp.status} ${detail.slice(0, 200)}`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!text || !text.trim()) {
  throw new Error('规划文本不能为空');
}
if (!['TD', 'BU'].includes(direction)) {
  throw new Error('direction 必须是 TD 或 BU');
}

Type guard

function isPlanDirection(d: string): d is 'TD' | 'BU' {
  return d === 'TD' || d === 'BU';
}

Try / catch

try {
  const plan = await buildPlan(text, direction);
} catch (err) {
  const status = /:(\s*)(\d{3})$/.exec(String((err as Error).message))?.[2];
  if (status === '404') setApiBaseHint();
  else if (status === '422') showValidationError();
  else showRetryableError();
}

Prevention

When it happens

Trigger: POST {API_BASE}/api/plan with body {text, direction} returns 4xx/5xx: 404 when API_BASE (from VITE_API_BASE_URL) points at the wrong host or the backend route is missing, 422 when text/direction fail backend validation (direction must be 'TD'/'BU' etc.), 500 when the downstream LLM/plan service fails, 502/503 when the backend is down or behind a misconfigured proxy.

Common situations: VITE_API_BASE_URL unset or wrong in .env so requests hit the Vite dev server instead of the API; CORS rejection surfacing as an opaque network error or a 404 from the dev server; backend not started; reverse proxy (nginx) not forwarding /api to the backend service.

Related errors


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