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

  1. Verify the backend serves GET /health: curl -i http://127.0.0.1:8000/api/health (note the /api prefix is part of base)
  2. Set VITE_API_BASE_URL correctly at build time to the publicly reachable, https API origin
  3. Ensure /health exists, returns 200 quickly, and is exempt from auth
  4. 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

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


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