Budibase/budibase · error · Error
Failed to fetch file from URL: ${fallbackResponse.statusText
Error message
Failed to fetch file from URL: ${fallbackResponse.statusText} What it means
After an attempt to pass the file to the LLM via upload fails, processUrlFile falls back to inlining: it re-fetches the file URL itself and, if that fallback fetch is not OK, throws with the fallback response's statusText. This is the same download failure as the primary path but reached via the upload-failure fallback branch.
Source
Thrown at packages/server/src/automations/steps/ai/extract.ts:169
return { kind: "image", value: toImageDataUrl(data, fileType) }
}
const filename = `document.${fileType || "pdf"}`
try {
const uploaded = await llm.uploadFile(
response.body as Readable,
filename,
fileType
)
return {
kind: "file",
value: uploaded,
}
} catch (error) {
if (shouldInlineFileAfterUploadFailure(error)) {
const fallbackResponse = await fetchWithBlacklist(fileUrl)
if (!fallbackResponse.ok) {
throw new Error(
`Failed to fetch file from URL: ${fallbackResponse.statusText}`
)
}
const data = await fallbackResponse.buffer()
const text = await extractPdfText(data)
return { kind: "text", value: text }
}
throw error
}
}
async function processAttachmentFile(
attachment: any,
llm: LLMResponse
): Promise<ExtractInput> {
const bucket = objectStore.ObjectStoreBuckets.APPS
const { stream } = await objectStore.getReadStream(bucket, attachment.key!)
const contentType = attachment.extensionView on GitHub (pinned to a81a902e9a)
Solutions
- Confirm the file URL returns 200 with curl and replace it with a working URL
- Re-upload the file to accessible storage and update the step's fileUrl
- If the upload failure is persistent, check LLM provider status/quota so the fallback isn't needed
- Retry the automation if the upstream outage was transient
Example fix
// before fileUrl: "https://example.com/tmp/report.pdf" // signed URL expired → 403 // after fileUrl: "https://example.com/permanent/report.pdf" // 200
Defensive patterns
Strategy: fallback
Validate before calling
const check = await fetchWithBlacklist(fileUrl)
if (!check.ok) throw new Error(`Source URL dead before run: ${check.status}`) Try / catch
try {
const input = await processUrlFile(params, fileUrl, fileType, llm)
} catch (err) {
if (err.message.startsWith("Failed to fetch file from URL:")) {
// both upload and inline fallback failed; surface URL as unusable
}
throw err
} Prevention
- Ensure the URL works independently of the LLM upload path
- Use permanent hosting for files used in automations
- Monitor LLM provider availability so the fallback path isn't hit unexpectedly
When it happens
Trigger: shouldInlineFileAfterUploadFailure(error) is true (LLM upload failed) and the subsequent fetchWithBlacklist(fileUrl) returns non-OK (404/403/5xx), so the inline-text fallback cannot download the file either.
Common situations: LLM upload fails AND the source URL has expired or returns errors; transient upstream outages hit both the upload and the direct fetch; rate-limited or IP-blocked asset host.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Failed to fetch file from URL: ${response.statusText}
- Failed to download asset: ${response.statusText}
- Redirects are not permitted.
- Maximum redirect reached.
- Failed to download SharePoint file (${response.status})
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/3589989349cb13ae.
Report an issue: GitHub.