{"record":{"id":"d83cd264a38b9ac8","repo":"Budibase/budibase","slug":"failed-to-fetch-import-data-status-response-sta","errorCode":null,"errorMessage":"Failed to fetch import data (status ${response.status})","messagePattern":"Failed to fetch import data \\(status (.+?)\\)","errorType":"http","errorClass":"HTTPError","httpStatus":502,"severity":"error","filePath":"packages/server/src/api/controllers/query/import/index.ts","lineNumber":103,"sourceCode":"\n  if (parsed.username || parsed.password) {\n    throw new HTTPError(\"Import url must not contain credentials\", 400)\n  }\n\n  return parsed\n}\n\nasync function fetchFromUrl(url: string): Promise<string> {\n  try {\n    // validate protocol / credentials up front for clear 400 errors\n    parseImportUrl(url)\n    // fetchWithBlacklist resolves and validates the target, pins the request to\n    // the validated IP (preventing DNS rebinding between validation and the\n    // actual connection) and safely follows redirects, re-validating each hop.\n    const response = await utils.fetchWithBlacklist(url)\n\n    if (!response.ok) {\n      throw new HTTPError(\n        `Failed to fetch import data (status ${response.status})`,\n        response.status\n      )\n    }\n\n    return await response.text()\n  } catch (error: any) {\n    if (error instanceof HTTPError) {\n      throw error\n    }\n    const message = error?.message || \"Unknown error\"\n    throw new HTTPError(`Failed to fetch import data - ${message}`, 502)\n  }\n}\n\nexport async function getImportInfo(\n  input: { data: string } | { url: string }\n): Promise<ImportInfo> {","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/query/import/index.ts#L85-L121","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"// before\nawait createImporter({ url: \"https://petstore.example.com/swagger/ui\" }) // 404\n// after\nawait createImporter({ url: \"https://petstore.example.com/v2/swagger.json\" })","handlingStrategy":"try-catch","validationCode":"const res = await fetch(url, { method: \"HEAD\" })\nif (!res.ok) throw new Error(`Spec URL returned ${res.status} before import`)","typeGuard":"null","tryCatchPattern":"try {\n  await createImporter({ url })\n} catch (e) {\n  if (e instanceof HTTPError && e.status === 404) {\n    // spec missing: ask user to re-host or paste the spec\n  } else if (e instanceof HTTPError && [429, 500, 502, 503].includes(e.status)) {\n    // retryable upstream error\n  }\n  throw e\n}","preventionTips":["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"],"tags":["http","network","import"],"backgroundTag":"http-non-2xx-response","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}