datawhalechina/hello-agents · error
请求失败
Error message
请求失败
What it means
This is a generic wrapper in a hand-rolled API client class: when fetch() returns a non-2xx response, it tries to parse the body as JSON and throws the server's message field, falling back to the literal '请求失败' (request failed). The fallback fires when the response body is not JSON or has no message field, so all server-side error detail is lost. It also does not propagate the HTTP status code onto the Error object.
Source
Thrown at Co-creation-projects/Apricity-InnocoreAI/frontend/static/js/app.js:501
async request(endpoint, options = {}) {
const token = localStorage.getItem('token');
const url = `${this.baseURL}${endpoint}`;
const config = {
headers: {
'Content-Type': 'application/json',
...(token && { 'Authorization': `Bearer ${token}` }),
...options.headers
},
...options
};
const response = await fetch(url, config);
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || '请求失败');
}
return await response.json();
}
get(endpoint) {
return this.request(endpoint);
}
post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data)
});
}
put(endpoint, data) {
return this.request(endpoint, {View on GitHub (pinned to 606a07d341)
Solutions
- Read the response body safely with text() first, try JSON.parse, and surface status code plus parsed detail/message in the thrown error
- Attach status (err.status = response.status) so callers can branch on 401/403/422
- Check response headers/content-type before attempting JSON parse to avoid SyntaxError replacing the real error
- Verify the backend actually returns {message: ...} in its error envelope, or align the field name with the backend contract
Example fix
// before
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || '请求失败');
}
// after
if (!response.ok) {
const text = await response.text().catch(() => '');
let message = '';
try { message = JSON.parse(text)?.message || JSON.parse(text)?.detail || ''; } catch (_) {}
const err = new Error(message || `请求失败(${response.status})`);
err.status = response.status;
throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!token && endpointRequiresAuth) { throw new Error('未登录'); } Type guard
function isApiError(e) { return e instanceof Error && typeof e.status === 'number'; } Try / catch
try { await api.post(...) } catch (e) { if (e.status === 401) logout(); else showToast(e.message); } Prevention
- Always include response status on thrown errors
- Parse body with text()+JSON.parse guarded by try/catch, never bare response.json()
- Agree on one error envelope ({message} or {detail}) with the backend and enforce it
When it happens
Trigger: Any request through this.request() whose backend answers 4xx/5xx, or answers with non-JSON body (HTML error page, plain text, empty body from a proxy), or JSON like {detail: '...'} (FastAPI style) instead of {message: '...'}. Also response.json() itself can throw a SyntaxError on non-JSON bodies, producing a different confusing error.
Common situations: Backend FastAPI returns {detail}; gateway/nginx returns HTML 502; token expired returning 401 with empty body; CORS preflight failure making response.ok false; running frontend against wrong API base URL.
Related errors
- HTTP ${response.status}
- 研究请求失败,状态码:${response.status}
- HTTP ${res.status}
- 服务器返回错误状态:${response.status}
- 请求失败(${res.status})
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/5b7314f677933eda.
Report an issue: GitHub.