How to catch silent NS_ERROR_OUT_OF_MEMORY in Chrome

Viewed 67

I tested the loading of very large files with XMLHttpRequest and noticed an interesting behavior of Chrome (90.0.4430.212): It loads the full file, but finishes with a 200-OK code and and empty (!) result. First I thought it was a silent timeout or whatever, but no, it seems to be a reached memory limit.

Trying it in Firefox (13.0esr (64-bit)) took for ages, but in the end I knew more: The Transfer itself did not trigger an "error" or a "timeout" event, resulted with 200 and empty result as well. But it threw an error:

Exception { name: "NS_ERROR_OUT_OF_MEMORY", message: "", result: 2147942414, filename: "http://localhost/testcenter-backend/vo_data/teterei.html", lineNumber: 16, columnNumber: 0, data: null, stack: "transferComplete@http://localhost/testcenter-backend/vo_data/teterei.html:16:9\n" }

So it has nothing to do with the transport itself, but apparently a memory limit reached when trying to do anything with the result. When I don't use the oReq.response, the error does not appear.

Okay, how to handle this? In Firefox I can catch the error with a simple try catch block. But this does not work for Chrome. A naive approach would be just to check if the resulting content is empty, but I wonder if there is another possibility to detect this stuff happening.

--

How to reproduce:

  1. Create a huge file.

I generated a 10,4GB file this way:

dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*10000]
  1. Run this code in a browser to load it.

  const oReq = new XMLHttpRequest();

  function updateProgress (oEvent) {
    console.log("progress", oEvent.loaded);
  }

  function transferComplete(evt) {
    console.log("The transfer is complete.", oReq.getAllResponseHeaders(), oReq.status);
    console.log(oReq.response); // here too much memory is allocated
  }

  function transferFailed(evt) {
    console.log("error", oReq.getAllResponseHeaders(), oReq.status);
  }

  function transferCanceled(evt) {
    console.log("cancel", oReq.getAllResponseHeaders(), oReq.status);
  }

  function timeOut(evt) {
    console.log("timeout", oReq.getAllResponseHeaders(), oReq.status);
  }

  oReq.addEventListener("progress", updateProgress);
  oReq.addEventListener("load", transferComplete);
  oReq.addEventListener("error", transferFailed);
  oReq.addEventListener("abort", transferCanceled);
  oReq.addEventListener("timeout", timeOut);

  // your huge file here instead
  oReq.open("GET", "https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js"); // URL to huge file here

  oReq.send();

The actual memory limit may vary to your system.

0 Answers
Related