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

  1. Confirm the backend service is running and reachable (e.g. curl http://localhost:4001/health).
  2. Check the browser devtools Network/Console tab for the underlying fetch error (CORS, DNS, mixed content).
  3. Verify the URL passed to the API call is absolute/valid and matches the configured proxy.
  4. 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

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


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/e9e2400ffe28074a. Report an issue: GitHub.