The file was never actually broken
The Portfolio Video Publisher workflow posts short build-breakdown videos — real n8n workflows, explained — to a Facebook Page, an Instagram account, and Threads, once a day. One run failed at the Facebook step with Unable to fetch video file from URL, a Graph API error that means Meta's own servers tried to download the file_url passed in the request and couldn't.
The URL in question, https://phonezait.de/portfolio-videos/system_health_check.mp4, was checked directly after the fact: a plain curl HEAD request returns 200 OK, Content-Type: video/mp4, and a normal content length. Nothing about the file, its path, or nginx's handling of that path is broken. That rules out the two most common causes of this specific Graph API error — a URL that isn't actually publicly reachable, or a file that's missing or corrupted — leaving a transient failure on Meta's end fetching the file at that particular moment as the most likely explanation.
Why "the URL works when I check it" isn't the same as "it worked when Facebook tried"
Facebook's video upload-by-URL flow has Meta's own infrastructure reach out and download the file server-side, separate from and after whatever request Meta's API gateway itself received. That download can fail for reasons that have nothing to do with the source server — a timeout on Meta's crawler, a transient DNS hiccup on their end, temporary rate limiting between Meta's data centers and an external host. None of that shows up as anything wrong from the source side; the server logs a normal successful request whenever anyone actually re-checks the URL, because the URL genuinely is fine by the time anyone looks.
That's the same shape of problem as the Google Sheets 503s covered elsewhere on this site: an external service having a bad moment on one specific call, with no way to reproduce it on demand and nothing actually wrong to "fix" in the usual sense.
The fix: treat it like any other flaky external fetch
The Post to Facebook node had no retryOnFail configured — confirmed by reading its live configuration before making any change. It was updated via the n8n API to retryOnFail: true, maxTries: 3, waitBetweenTries: 3000, matching the pattern already used for the workflow's Google Sheets 503 issue and the Groq rate-limit fix covered elsewhere on this site. If Meta's fetch fails once, the node now gets two more chances, three seconds apart, before the whole publish attempt for that video is marked as failed.
This doesn't fix a bug in the traditional sense — there was nothing wrong with the request, the file, or the hosting — it just stops a single unlucky moment on Meta's infrastructure from silently costing this workflow a day's post on one platform while Instagram and Threads (posted by separate nodes downstream) go out normally.
What confirmed it
The node's configuration was read back from the n8n API after the change: retryOnFail: true, maxTries: 3, waitBetweenTries: 3000 on Post to Facebook. The source video URL was independently re-verified as reachable and correctly served, which is what points at a transient fetch failure on Meta's side rather than anything actually broken here. The workflow was re-fetched and is still active: true.
Ruling out the causes that are not transient
A retry only helps if the cause is a temporary failure on Meta's side. Before relying on it, the URL should pass these checks, all from a machine outside your own network:
| Check | Command or method | Expected |
|---|---|---|
| Status and type | curl -sI <url> | 200 and Content-Type: video/mp4 |
| No redirect chain | curl -sIL <url> | One response, or a single redirect to HTTPS |
| Full file served | Compare Content-Length with the file on disk | Same size |
| No bot blocking | Firewall, rate limits or a WAF in front of the server | Meta's fetcher is not blocked |
| Valid certificate | curl without -k | No certificate error |
| File is complete when posted | Upload or render finished before the API call | No partially written file |
The last one is easy to miss: if a workflow posts the URL while another process is still writing the file, Meta's fetcher gets a truncated video. That fails intermittently, just like a transient error, but a retry three seconds later may fetch the same incomplete file.
An upload that doesn't depend on Meta fetching your server
If file_url keeps failing for a specific host, the Graph API also accepts the video file itself. In n8n that means reading the file as binary data (for example with an SSH download or a Read Binary File step) and sending it to the /videos endpoint as multipart form data in the field source. For large files Meta documents a resumable upload flow. It is more work to set up, but it removes the dependency on Meta reaching your server at that moment.
Keeping one platform's failure from stopping the rest
In a workflow that posts to several platforms in a row, a failed Facebook node also stops everything after it. Setting the Facebook node to continue on error, with an alert on its error output, lets Instagram and Threads still go out, and the failed platform can be retried by hand later. Combined with retries, a single bad moment on one platform then costs at most one post on that platform.
Frequently asked questions
What does 'Unable to fetch video file from URL' mean on Facebook?
Meta's servers tried to download the file_url you passed and could not. The cause can be your server, the file, or a temporary problem on Meta's side.
How do I tell a transient failure from a real problem?
Check from outside your network that the URL returns 200 with video/mp4, has no redirect chain, serves the full file and isn't blocked by a firewall. If all of that passes, a retry is the right fix.
Can I upload the video file directly instead of a URL?
Yes. Send the file as binary data in the source field of a multipart request to the /videos endpoint, or use Meta's resumable upload for large files.
Which retry settings did you use?
Retry On Fail with 3 tries and 3,000 ms between tries on the node that posts to Facebook.
n8n Automation Hub