TFJS returns memory access out of bound error?

This function used to remove background from a selfie image, and this runs on a mobile device, and if this function runs more than five times consecutively, it throws following error,

E/Capacitor/Console: File: http://localhost/vendor-es2015.js - Line 61524 - Msg: ERROR Error: Uncaught (in promise): RuntimeError: memory access out of bounds
RuntimeError: memory access out of bounds
at http://localhost/assets/tf-wasm/tfjs-backend-wasm.wasm:wasm-function[9]:0xaef
at http://localhost/assets/tf-wasm/tfjs-backend-wasm.wasm:wasm-function[180]:0x16f01
at BackendWasm.disposeData (http://localhost/editor-editor-module-es2015.js:84977:23)
at Engine.disposeTensor (http://localhost/editor-editor-module-es2015.js:82856:26)
at Tensor.dispose (http://localhost/editor-editor-module-es2015.js:51006:21)
at Engine.endScope (http://localhost/editor-editor-module-es2015.js:82975:24)
at http://localhost/editor-editor-module-es2015.js:82479:71
at Engine.scopedRun (http://localhost/editor-editor-module-es2015.js:82495:13)
at Engine.tidy (http://localhost/editor-editor-module-es2015.js:82479:21)
at tidy (http://localhost/editor-editor-module-es2015.js:124425:59)

And the function is following,

async removeBackGround(imageData) {
const ref_size = 512;

try {
  let tensor: any = tf.browser.fromPixels(imageData, 3);

  const offset = tf.scalar(127.5);
  tensor = tf.cast(tensor, "float32");
  tensor = tf.sub(tensor, offset);
  tensor = tf.div(tensor, offset);
  tensor = tf.image.resizeBilinear(tensor, [ref_size, ref_size]);

  tensor = tf.expandDims(tensor);

  let res: any = await this.model.predict(tensor);

  res = tf.image.resizeBilinear(res, [imageData.height, imageData.width]);

  res = tf.squeeze(res);
  // let matcanvas: any = document.getElementById("backgroundCanvas");
  let matcanvas = document.createElement("canvas");
  matcanvas.width = imageData.width + 10 * 2;
  matcanvas.height = imageData.height + 10 * 2;

  console.log('matcanvas.width', matcanvas.width);
  console.log('matcanvas.height', matcanvas.height);


  // tf.browser.toPixels(res, matcanvas);
  res = tf.mul(res, offset);
  res = tf.add(res, offset);
  res = tf.cast(res, "int32");
  let arr = res.dataSync();

  let imageDataWithOutAlpha = this.removeAlpha(imageData.data);

  let idx = 0;
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] < 200) {
      imageDataWithOutAlpha[idx] = 255;
      imageDataWithOutAlpha[idx + 1] = 255;
      imageDataWithOutAlpha[idx + 2] = 255;
    }
    idx += 3;
  }

  let imageDataBackWithAlpha = this.addAlpha(imageDataWithOutAlpha);
  let buffer: any = new Uint8ClampedArray(imageDataBackWithAlpha);

  const ctx: any = matcanvas.getContext("2d", { antialias: false });
  ctx.fillStyle = "#c3c3c3";
  // fill it with border colour
  ctx.fillRect(0, 0, matcanvas.width, matcanvas.height);

  var idata = ctx.createImageData(imageData.width, imageData.height);

  idata.data.set(buffer);

  ctx.putImageData(idata, 10, 10)

  let bgRemoved = matcanvas.toDataURL();

 
  return bgRemoved;
} catch (error) {


  throw error
} finally {
  tf.disposeVariables();

  tf.dispose();
  alert('TF disposed !')
}
}

When you create Tensors in memory you must manually dispose of them after you have finished using them. The JS garbage collector will not free up the memory - you must call .dispose() on any returned tensors after you are finished using them else you will have a memory leak as you have here.

You may be interested in learning more about Tensor disposal in my new course here that is free and talks about such matters: