{"record":{"id":"c1c15a42e01252a2","repo":"Budibase/budibase","slug":"failed-to-fetch-import-data-message","errorCode":null,"errorMessage":"Failed to fetch import data - ${message}","messagePattern":"Failed to fetch import data - (.+?)","errorType":"http","errorClass":"HTTPError","httpStatus":502,"severity":"error","filePath":"packages/server/src/api/controllers/query/import/index.ts","lineNumber":115,"sourceCode":"    // 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> {\n  const importer = await createImporter(input)\n  return importer.getInfo()\n}\n\nasync function urlToSpecs(url: string, cacheKeyBase?: string): Promise<string> {\n  if (!cacheKeyBase) {\n    const result = await fetchFromUrl(url)\n    return result\n  }\n\n  const cacheKey = `${cacheKeyBase}:specs`\n  const client = await redis.clients.getOpenapiImportSpecsClient()","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/query/import/index.ts#L97-L133","documentation":"This is the catch-all wrapper in fetchFromUrl: any non-HTTPError failure during the URL fetch (DNS failure, connection refused, timeout, TLS error, or invalid URL rejected by parseImportUrl... though that path rethrows as HTTPError) is converted into an HTTPError with status 502 and the underlying error message appended. It tells you the fetch itself blew up rather than returning a bad status.","triggerScenarios":"fetchWithBlacklist throws because the host cannot be resolved (ENOTFOUND), the connection is refused (ECONNREFUSED), the TLS handshake fails, a redirect leads to a blocked/blacklisted IP, or the request times out.","commonSituations":"Importing from a URL in an air-gapped/private network the server cannot reach; typos in the hostname (e.g. http://localhsot); self-signed certificates; SSRF protection rejecting a redirect to an internal address.","solutions":["Read the appended message (e.g. ENOTFOUND, ECONNREFUSED, self signed certificate) to identify the transport failure","Verify the hostname resolves and the port is reachable from the Budibase server, not just your machine","If the spec is internal, host it on an address the server can access or paste the spec content as `data`","Fix TLS issues by using a properly signed certificate (or importing your CA into the Node trust store)"],"exampleFix":"// before\nawait createImporter({ url: \"http://internal-spec.local/openapi.yaml\" }) // ENOTFOUND\n// after\nawait createImporter({ data: fs.readFileSync(\"openapi.yaml\", \"utf8\") })","handlingStrategy":"try-catch","validationCode":"const parsed = new URL(url)\nif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") throw new Error(\"Only HTTP(S) URLs allowed\")\nawait dns.promises.lookup(parsed.hostname) // must resolve from the server host","typeGuard":"null","tryCatchPattern":"try {\n  await createImporter({ url })\n} catch (e) {\n  const msg = String(e?.message ?? \"\")\n  if (msg.includes(\"ENOTFOUND\") || msg.includes(\"ECONNREFUSED\")) {\n    // network/DNS problem: fix host or run where reachable\n  } else if (msg.includes(\"certificate\")) {\n    // TLS problem: install CA or use https with valid cert\n  }\n  throw e\n}","preventionTips":["Test the URL from the same machine/network as the Budibase server before importing","Use hostnames that resolve in the server's DNS (not your laptop's /etc/hosts only)","Use valid TLS certificates on spec hosts; avoid self-signed certs","Remember SSRF protections may block internal/redirected addresses — host specs somewhere allowlisted"],"tags":["network","dns","tls","import"],"backgroundTag":"fetch-network-failure","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}