datawhalechina/hello-agents · critical
No reachable backend API. Tried: ${candidateBases.join(', ')
Error message
No reachable backend API. Tried: ${candidateBases.join(', ')} What it means
Backend discovery failure: at startup the client builds candidateBases (VITE_API_BASE_URL env var, then http://127.0.0.1:8000/api, http://localhost:8000/api, and ${protocol}//${currentHost}:8000/api) and probes each with GET {base}/health (3s timeout) until one answers. If none do, it throws listing all tried bases. The result is cached in activeBase, so one failure is retried on every call.
Source
Thrown at Co-creation-projects/monkeyhlj-NetworkHealthReportAgent/frontend/src/api.js:40
const api = axios.create({ timeout: API_TIMEOUT })
async function resolveBase() {
if (activeBase) {
return activeBase
}
for (const base of candidateBases) {
try {
await axios.get(`${base}/health`, { timeout: 3000 })
activeBase = base
return base
} catch (_) {
// Try next candidate
}
}
throw new Error(`No reachable backend API. Tried: ${candidateBases.join(', ')}`)
}
async function apiGet(path, config = {}) {
const base = await resolveBase()
return api.get(`${base}${path}`, config)
}
async function apiPost(path, body = {}, config = {}) {
const base = await resolveBase()
return api.post(`${base}${path}`, body, config)
}
export async function fetchSites() {
const { data } = await apiGet('/sites')
return data.sites
}
export async function fetchReport(siteId, startDate, endDate) {View on GitHub (pinned to 606a07d341)
Solutions
- Verify the backend serves GET /health: curl -i http://127.0.0.1:8000/api/health (note the /api prefix is part of base)
- Set VITE_API_BASE_URL correctly at build time to the publicly reachable, https API origin
- Ensure /health exists, returns 200 quickly, and is exempt from auth
- For https deployments, serve the API over https or proxy it under the same origin so probes aren't blocked as mixed content
Example fix
// before
bases.push('http://127.0.0.1:8000/api');
bases.push('http://localhost:8000/api');
bases.push(`${protocol}//${currentHost}:8000/api`);
// after (prefer same-origin proxy in prod; skip http candidates on https pages)
if (protocol !== 'https:') {
bases.push('http://127.0.0.1:8000/api', 'http://localhost:8000/api', `${protocol}//${currentHost}:8000/api`);
} else {
bases.push(`${protocol}//${currentHost}/api`); // reverse-proxied same origin
} Defensive patterns
Strategy: fallback
Validate before calling
async function probe(base) { try { const r = await axios.get(`${base}/health`, { timeout: 3000 }); return r.status === 200; } catch { return false; } } const ok = await probe(VITE_API_BASE_URL ?? defaultBase); if (!ok) showSetupError(); Try / catch
try { await apiGet('/report'); } catch (e) { if (e.message.startsWith('No reachable backend')) showBackendDownBanner(); else throw e; } Prevention
- Set VITE_API_BASE_URL correctly at build time for deployed environments
- Serve /health unauthenticated, fast, and with CORS enabled
- Avoid http:// candidates on https pages (mixed content)
- Clear/re-probe activeBase on failure instead of caching forever
When it happens
Trigger: Backend not running on port 8000; backend running but /health route missing or erroring; VITE_API_BASE_URL set to a wrong/stale URL; accessing from another device where 127.0.0.1/localhost point nowhere and currentHost:8000 is firewalled; https page probing http:// candidates gets blocked by mixed-content rules.
Common situations: Deployed frontend (https) cannot probe http://127.0.0.1:8000 (mixed content) and backend host:8000 is not exposed publicly; VITE_API_BASE_URL typo'd during build; backend started without the /health endpoint; corporate network blocks non-standard ports.
Related errors
- HTTP error: ${response.status}
- 系统状态异常
- RECOMMEND_UNAVAILABLE
- 前端文件缺失,请检查 historical_review/web/static/
- 服务不可用: {str(e)}
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/34f0b30d10e264fa.
Report an issue: GitHub.