{"record":{"id":"6812dbe4d1ae3a74","repo":"Budibase/budibase","slug":"failed-to-fetch-file-from-url-response-statuste","errorCode":null,"errorMessage":"Failed to fetch file from URL: ${response.statusText}","messagePattern":"Failed to fetch file from URL: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/automations/steps/ai/extract.ts","lineNumber":146,"sourceCode":"            MAX_INLINE_DOC_TEXT_LENGTH\n          )}`\n\n  return [\n    {\n      role: \"user\",\n      content: userContent,\n    },\n  ]\n}\n\nasync function processUrlFile(\n  fileUrl: string,\n  fileType: SupportedFileType,\n  llm: LLMResponse\n): Promise<ExtractInput> {\n  const response = await fetchWithBlacklist(fileUrl)\n  if (!response.ok) {\n    throw new Error(`Failed to fetch file from URL: ${response.statusText}`)\n  }\n\n  if (isImageType(fileType)) {\n    const data = await response.buffer()\n    return { kind: \"image\", value: toImageDataUrl(data, fileType) }\n  }\n\n  const filename = `document.${fileType || \"pdf\"}`\n  try {\n    const uploaded = await llm.uploadFile(\n      response.body as Readable,\n      filename,\n      fileType\n    )\n    return {\n      kind: \"file\",\n      value: uploaded,\n    }","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/automations/steps/ai/extract.ts#L128-L164","documentation":"processUrlFile downloads the user-supplied file URL via fetchWithBlacklist and throws when the response is not OK, surfacing the HTTP statusText. This is the initial fetch path before any upload/fallback logic runs.","triggerScenarios":"fetchWithBlacklist(fileUrl) returns a non-OK status (404, 403, 410, 5xx) while processing a URL-sourced file in the AI extract automation step.","commonSituations":"User pasted a wrong or dead link into the extract step; file hosted behind auth or an expired signed URL; SSRF guard passes but server returns an error; server hosting the file is down.","solutions":["Open the URL in a browser/curl to confirm it returns the file with 200","Re-upload the file and use a fresh URL (prefer Budibase attachments) in the step input","If the file requires auth, host it somewhere publicly readable or use attachment source instead","Check for typos or URL-encoding issues in the configured file URL"],"exampleFix":"// before\nsource: URL, fileUrl: \"https://example.com/old-report.pdf\" // 404\n// after\nfileUrl: \"https://example.com/reports/report-2026.pdf\" // 200","handlingStrategy":"validation","validationCode":"const pre = await fetchWithBlacklist(fileUrl)\nif (!pre.ok) {\n  throw new Error(`File URL is not reachable: ${pre.status} ${pre.statusText}`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  const input = await processUrlFile(params, fileUrl, fileType, llm)\n} catch (err) {\n  if (err.message.startsWith(\"Failed to fetch file from URL:\")) {\n    // ask the user for a fresh URL or fall back to attachment upload\n  }\n  throw err\n}","preventionTips":["Test file URLs in a browser before configuring the step","Avoid links behind auth or with short-lived signatures","Prefer Budibase attachment uploads over arbitrary external URLs"],"tags":["http","fetch","network","ai","file-download"],"backgroundTag":"http-request-failed","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}