firefoxxmlhttprequestfetch

Uploading a Certain Combination of Files Consistently Fails with Firefox, but Succeeds in Edge and Chrome


My team and I maintain a legacy PHP web application for large file transfers. The application stack is LAMP-like, leveraging NGINX and PHP-FPM. Recently, we have observed Firefox failing to upload a certain combination of files. When the page was using XHR, the progress bar tied to it would jump immediately 99% and then eventually fail to upload. Looking more closely at progress event, we observed that the loaded value appeared to be too large right from the start.

Reworking the page to use Fetch did not fix the problem, but it did make it easier to determine that the transfer was failing due to a network type error, not due to a failure response from the backend.

Neither Edge nor Chrome exhibit these same failures. Even more strangely, if the individual files are uploaded, Firefox succeeds in uploading them. If they are all zipped together, Firefox also succeeds in uploading them. It is only when they are appended individually to the form data that for the POST that Firefox fails.

We have attempted to rule out virus scanner or firewall interference by attempting the upload from non-work computers. We have also downgraded Firefox a few times to see if a recent upgrade was culprit. We have cleared out cookies and cache, reset profiles, ran the browser in Safe Mode, too.

NGINX access and error logs are showing nothing. No PHP errors. We are fairly stumped here and have been pretty exhaustive in our testing, research, and troubleshooting efforts.

We have also examined other Stack Overflow questions and answers that seemed relevant.

Why does Firefox consistently fail to upload a particular combination of files with a network error when other browsers succeed and Firefox itself succeeds if those files are instead uploaded individually or in a large zip file?


Solution

  • Microsoft Copilot was able to come up with some information that explains why the issue occurs and provide some potential workarounds:

    Why Firefox Fails on Multi-File FormData Uploads

    If you append more than one File object to a single FormData and POST it in Firefox, you’ll immediately see the upload “finish” (progress jumps to 100%) and then a NetworkError. Chrome and Edge never hit this failure, and even Firefox will upload those same files just fine if you:

    What’s Happening Under the Hood

    1. Firefox pre-buffers the entire multipart body
      Firefox’s XHR/Fetch implementation must know the final Content-Length before it hits the wire. To do that it internally builds (buffers) your entire multipart body in an nsPipe. With multiple File entries—even if each one streams off disk by itself—the combination goes down a code path that fully buffers those streams and calculates length up front.

    2. A corner-case in that buffering code trips a network failure
      For some sets of files (size, type, metadata, boundary math) Firefox’s multipart builder errors out mid-buffer. The underlying I/O call returns a failure (e.g. NS_ERROR_FAILURE), so the POST is immediately aborted at the network stack level.

    3. Progress events lie by spec
      The spec mandates that right before the error event fires, the final progress is dispatched with loaded == total. That’s why you see the bar jump to 100%—even though nothing ever reached the server—followed immediately by the network error.

    4. Chrome/Edge avoid this by streaming chunked bodies
      Those browsers never need to pre-buffer the entire form payload. They stream each part as it becomes available, so they never hit the buggy code path that fails under Firefox’s multipart builder.

    Proof and Bug References

    Workarounds

    1. Upload files one at a time

      for (let file of files) { const fd = new FormData(); fd.append('file', file); await fetch('/upload', { method: 'POST', body: fd }); }

    2. Zip on the client into one Blob
      Combine all files into a single zip‐Blob (e.g. with JSZip), then append that one blob to your FormData. Firefox’s code path for a single blob upload doesn’t hit the broken multipart builder.

    3. Use a streaming multipart generator
      Bypass FormData entirely and construct the body as a ReadableStream, writing boundaries and file chunks yourself. Firefox will stream it without pre-buffering.

    4. Detect Firefox and fall back
      If you detect navigator.userAgent contains “Firefox,” switch to one of the above strategies.

    When Will It Be Fixed?

    This is a known Firefox bug in the multipart handling layer. Follow or star the upstream Bugzilla issue:

    Until it lands in a stable Firefox release, apply one of the workarounds above whenever you need to upload multiple files in one go under Firefox.