datawhalechina/hello-agents · error
HTTP ${res.status}
Error message
HTTP ${res.status} What it means
Thrown when POST ${API_BASE}/api/diet/recommend returns a non-OK status. The handler first tries res.json() (with .catch(()=>({})) so a non-JSON body never crashes), then throws either JSON.stringify(data.detail) if the FastAPI-style detail field exists, or the bare 'HTTP <status>' template when the body was empty/unparseable/ lacked detail.
Source
Thrown at Co-creation-projects/Shawnxyxy-HealthRecordAgent/frontend/app.js:301
user_id: userId,
context: {
today_food_log_text: foodLog,
goal: document.getElementById("dietGoal")?.value || "muscle_gain",
channels: ["convenience_store", "delivery"],
activity_context: document.getElementById("dietActivityContext")?.value?.trim() || "",
free_notes: document.getElementById("dietNotes")?.value?.trim() || "",
},
};
try {
const res = await fetch(`${API_BASE}/api/diet/recommend`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const data = await res.json().catch(() => ({}));
if (!res.ok) {
throw new Error(data.detail ? JSON.stringify(data.detail) : `HTTP ${res.status}`);
}
const runId = data.run_id;
try {
localStorage.setItem(LAST_DIET_RUN_KEY, runId);
} catch (_) { /* ignore */ }
const planning = data.planning || {};
const ver = data.schema_version || "1";
const mode = data.pipeline_mode || "legacy";
const tech = isDeveloperMode();
let html = "";
if (tech) {
html += `<p><strong>run_id</strong>:<code>${escapeHtml(runId)}</code> <small>schema=${escapeHtml(String(ver))} / ${escapeHtml(String(mode))}</small></p>`;
}
if (data.degraded) {
html += tech
? `<p class="banner banner-warning"><strong>降级</strong>:部分阶段使用规则/模板兜底,请查看 <code>errors</code>。</p>`View on GitHub (pinned to 606a07d341)
Solutions
- Reproduce with curl -i to see the real status and body; if 422 compare the request body keys with the endpoint's Pydantic model
- If body is empty (this literal message), check backend logs for an unhandled exception in /api/diet/recommend
- Pretty-print detail: if Array.isArray(data.detail) map loc/msg fields into a readable string instead of JSON.stringify
- Verify API_BASE and that the FastAPI service is listening
Example fix
// before
throw new Error(data.detail ? JSON.stringify(data.detail) : `HTTP ${res.status}`);
// after
const detail = Array.isArray(data.detail)
? data.detail.map(d => `${(d.loc||[]).join('.')}: ${d.msg}`).join('; ')
: (typeof data.detail === 'string' ? data.detail : '');
throw new Error(detail || `HTTP ${res.status} ${res.statusText || ''}`.trim()); Defensive patterns
Strategy: try-catch
Validate before calling
if (!userId) { showToast('请先选择用户'); return; } Type guard
function isDietResponse(d) { return d && typeof d.run_id === 'string' && typeof d.planning === 'object'; } Try / catch
try { const data = await postDietRecommend(body); } catch (e) { renderError(prettifyFastApiDetail(e.message)); } Prevention
- Validate form inputs client-side before POSTing
- Convert FastAPI array detail into readable text centrally
- Log run_id of successful calls to correlate with backend logs
When it happens
Trigger: Backend validation failure (422 with structured detail array, which then gets stringified into something like [{"loc":...}]), missing user_id or malformed body producing 422, 500 from the diet agent, backend not running so fetch itself rejects instead. Seeing the raw 'HTTP x' form means the error body was empty — typically a crashed worker or a proxy 502.
Common situations: FastAPI 422 validation details stringified and shown raw to users; backend restart mid-request; API_BASE pointing at wrong port; CORS blocking so fetch throws TypeError before this line.
Related errors
- 请求失败
- 研究请求失败,状态码:${response.status}
- 服务器返回错误状态:${response.status}
- 请求失败(${res.status})
- HTTP error: ${response.status}
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/e62673e3bf3a672c.
Report an issue: GitHub.