Budibase/budibase · error
Failed to send request
Error message
Failed to send request
What it means
makeApiCall wraps the underlying fetch() call; if fetch itself rejects (network failure, DNS error, CORS block, mixed-content, server unreachable) it throws an APIError 'Failed to send request'. AbortError from an AbortSignal is re-thrown as-is; all other request-level errors are converted to this generic message. Note this fires only when the request never got a response — HTTP error statuses are handled separately afterwards.
Source
Thrown at packages/frontend-core/src/api/index.ts:200
}
}
// Make request
let response: Response
try {
response = await fetch(url, {
method,
headers,
body: requestBody,
credentials: "same-origin",
signal,
})
} catch (error) {
delete cache[url]
if (signal?.aborted) {
throw error
}
throw makeError("Failed to send request", url, method)
}
// Handle response
if (response.status >= 200 && response.status < 400) {
handleMigrations(response)
try {
if (response.status === 204) {
return undefined as ResponseT
} else if (parseResponse) {
return await parseResponse(response)
} else {
return (await response.json()) as ResponseT
}
} catch (error) {
delete cache[url]
throw `Failed to parse response: ${error}`
}
} else {View on GitHub (pinned to a81a902e9a)
Solutions
- Confirm the backend service is running and reachable (e.g. curl http://localhost:4001/health).
- Check the browser devtools Network/Console tab for the underlying fetch error (CORS, DNS, mixed content).
- Verify the URL passed to the API call is absolute/valid and matches the configured proxy.
- If the request was intentionally cancelled, check signal.aborted — abort errors surface unchanged and should be handled as cancellation, not failure.
Example fix
// before: hard-coded wrong port
api.get('http://localhost:4002/api/rows')
// after: derive base URL from config/proxy
api.get(`${window.location.origin}/api/rows`) Defensive patterns
Strategy: retry
Validate before calling
// pre-flight health check for local/self-hosted backends
const healthy = await fetch(`${baseUrl}/health`).then(r => r.ok).catch(() => false)
if (!healthy) throw new Error("Backend unreachable before API call") Type guard
const isAbort = (e: unknown): e is DOMException => e instanceof DOMException && e.name === "AbortError"
Try / catch
try {
return await api.get(url)
} catch (e) {
if (isAbort(e)) throw e // intentional cancellation
if (e?.message === "Failed to send request") {
await backoff(); return retry(() => api.get(url))
}
throw e
} Prevention
- Ensure backend services are running before issuing calls in dev
- Use relative/origin-derived URLs to avoid wrong-port mistakes
- Check CORS and mixed-content rules when calling external APIs
- Implement retry with backoff for transient network failures
- Treat abort errors separately from network failures
When it happens
Trigger: Any frontend-core API call where fetch() rejects: backend not running, wrong URL/port, network partition, CORS preflight failure, mixed http/https content, or invalid URL. Requests that were aborted via signal re-throw the original abort error instead.
Common situations: Local dev where the server (port 4001) or worker isn't started; proxy misconfiguration; calling an external API blocked by browser CORS; laptop offline or VPN drop mid-session.
Related errors
- Failed to connect to resolved IP for ${hostname}: unknown ne
- Exa error: ${response.status} ${response.statusText} - ${err
- Parallel error: ${response.status} ${response.statusText}
- Failed to download asset: ${response.statusText}
- Failed to fetch file from URL: ${response.statusText}
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/e9e2400ffe28074a.
Report an issue: GitHub.