Budibase/budibase · error · HTTPError
Failed to fetch import data (status ${response.status})
Error message
Failed to fetch import data (status ${response.status}) What it means
fetchFromUrl downloads REST import data (an OpenAPI spec or curl command) from a user-supplied URL. When the HTTP response has a non-2xx status (response.ok is false), it throws an HTTPError carrying the upstream status code. This distinguishes 'the server answered but refused the request' from transport-level failures.
Source
Thrown at packages/server/src/api/controllers/query/import/index.ts:103
if (parsed.username || parsed.password) {
throw new HTTPError("Import url must not contain credentials", 400)
}
return parsed
}
async function fetchFromUrl(url: string): Promise<string> {
try {
// validate protocol / credentials up front for clear 400 errors
parseImportUrl(url)
// fetchWithBlacklist resolves and validates the target, pins the request to
// the validated IP (preventing DNS rebinding between validation and the
// actual connection) and safely follows redirects, re-validating each hop.
const response = await utils.fetchWithBlacklist(url)
if (!response.ok) {
throw new HTTPError(
`Failed to fetch import data (status ${response.status})`,
response.status
)
}
return await response.text()
} catch (error: any) {
if (error instanceof HTTPError) {
throw error
}
const message = error?.message || "Unknown error"
throw new HTTPError(`Failed to fetch import data - ${message}`, 502)
}
}
export async function getImportInfo(
input: { data: string } | { url: string }
): Promise<ImportInfo> {View on GitHub (pinned to a81a902e9a)
Solutions
- Open the URL directly in a browser/curl to confirm what status it returns and fix the hosting/auth on the source side
- If the spec needs authentication, download it manually and paste the contents as `data` instead of `url`
- Retry later if the status is 429/5xx, as the upstream may be temporarily unavailable
- Verify the URL points at the raw spec file, not an HTML viewer page (e.g. Swagger UI)
Example fix
// before
await createImporter({ url: "https://petstore.example.com/swagger/ui" }) // 404
// after
await createImporter({ url: "https://petstore.example.com/v2/swagger.json" }) Defensive patterns
Strategy: try-catch
Validate before calling
const res = await fetch(url, { method: "HEAD" })
if (!res.ok) throw new Error(`Spec URL returned ${res.status} before import`) Type guard
null
Try / catch
try {
await createImporter({ url })
} catch (e) {
if (e instanceof HTTPError && e.status === 404) {
// spec missing: ask user to re-host or paste the spec
} else if (e instanceof HTTPError && [429, 500, 502, 503].includes(e.status)) {
// retryable upstream error
}
throw e
} Prevention
- Pre-flight check the URL returns 200 and content-type looks like JSON/YAML before importing
- Never point the import URL at an HTML docs page or an auth-protected resource
- Paste the spec content directly when the host requires authentication
When it happens
Trigger: Calling createImporter/getImportInfo with { url } where the remote host returns 404 (spec moved/renamed), 401/403 (spec requires auth), 500 (server error), or any other non-2xx status.
Common situations: Importing a Swagger URL that now redirects to a login page; a spec hosted behind a private repo that returns 404; a rate-limited API gateway returning 429; a self-hosted spec server that is misconfigured and returns 5xx.
Related errors
- Unexpected response when fetching openid-configuration: ${re
- unexpected response ${response.statusText}
- Unexpected response ${response.statusText}
- Failed to retrieve skeleton metadata
- Unable to retrieve docker-compose file - ${response.status}
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/d83cd264a38b9ac8.
Report an issue: GitHub.