onnxruntime icon indicating copy to clipboard operation
onnxruntime copied to clipboard

[Web] Cannot import from web worker

Open GregCornis opened this issue 6 months ago • 1 comments

Describe the issue

I have a working flow to run a segmentation model on pictures, and I'm trying to move this part of the code to a Web Worker. However, I have an error when creating the session, I believe because the dynamic import fails : WorkerGlobalScope.fetch: /_next/static/media/ort-wasm-simd-threaded.jsep.8296b855.wasm is not a valid URL.

Here is how I'm creating the Worker

  const analyser = useRef<Worker>(undefined);
  useEffect(
    () => { 
      const worker = new Worker(new URL("analyser.ts", import.meta.url)) 
      worker.onmessage = (e) => {
        console.log("Receive message from analyser", e.data);
      };
      worker.postMessage("Hi");
      analyser.current = worker;
      return () => {
        analyser.current?.terminate();
      };
    },
    []
  );

And here is the piece of code from analysis.ts that causes the problem

import { Tensor } from 'onnxruntime-web';
import * as ort from 'onnxruntime-web';
import { Jimp, JimpInstance } from "jimp";
import { Analysis } from "./utils";

self.onmessage = async (e) => {
  console.log("Analyser received", e.data);
  await runAnalysis(e.data, () => {}, () => {console.log("Analysis updated from worker")});
}

export async function runAnalysis(files: File[], setMask: (m: any) => void, setAnalysisResults: (m: Analysis[]) => void) {
  // BREAKS HERE
  const session = await ort.InferenceSession.create('/segmentation.onnx', { executionProviders: ['wasm'], graphOptimizationLevel: 'all' });
  console.log('Inference session created');

  for (const file of files) {
    const { resized, mask } = await runSegmentation(URL.createObjectURL(file), session);
    // SNIP
  }
}

The exact same code works when running not in a web worker, do you know what is happening ?

To reproduce

This is a very basic NextJS project, created with npx create-next-app@latest.
Then simply run npm install onnxruntime-web.
Create a analyse.ts file in the src directory. Then edit the page.tsx's Home function to add the above code, which creates the Worker and posts a message.

Urgency

No response

ONNX Runtime Installation

Released Package

ONNX Runtime Version or Commit ID

[email protected]

Execution Provider

'wasm'/'cpu' (WebAssembly CPU)

GregCornis avatar Jun 17 '25 14:06 GregCornis

Edit: I have managed to get it working in local by:

  • copying the ort-wasm-simd-threaded.jsep.mjs and ort-wasm-simd-threaded.jsep.wasm files to the public/ folder
  • setting ort.env.wasm.wasmPaths = "http://localhost:3002/"
  • specifying the model with absolute path ort.InferenceSession.create('http://localhost:3002/segmentation.onnx', { executionProviders: ['wasm'], graphOptimizationLevel: 'all' });

So I imagine there are some specificities on absolute / relative path for fetches in web workers, but I'm not sure what the rule is. I'd rather find a better solution than to hardcode the baseURI in the web worker, if possible.

GregCornis avatar Jun 17 '25 15:06 GregCornis

Hey @fs-eire or anyone ?

GregCornis avatar Jul 18 '25 06:07 GregCornis

could you share a complete repo so that I can debug on my side?

fs-eire avatar Jul 18 '25 19:07 fs-eire

Sorry it took a while, I have made a public repo here that you can checkout: https://github.com/GregCornis/OnnxDemoWebWorker.

Here is what it looks like when it works: Image

And here is the exact error msg: wasm streaming compile failed: TypeError: WorkerGlobalScope.fetch: /_next/static/media/ort-wasm-simd-threaded.jsep.8296b855.wasm is not a valid URL..

The repo has two branches:

  • main: the "broken" one, with the error mentioned
  • working: the working demo, which doesn't use a web worker

The diff between the two is pretty minimal, it just calls the function directly instead of going through the web worker:

diff --git a/src/app/page.tsx b/src/app/page.tsx
index 1a4b4cb..814877b 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -2,6 +2,7 @@

 import { useState, useEffect, ReactNode, useMemo, useRef, ChangeEvent } from "react";
 import { Analysis, UploadData } from './utils'
+import { runAnalysis } from "./analyser";


 export default function Home() {
@@ -66,7 +67,7 @@ export default function Home() {
               setUploads(uploads.concat([up]));
               setShowNewUpload(false);

-              analyser.current?.postMessage(up.files);
+              runAnalysis(up.files, () => {}, (analysis) => setUploads((prev: UploadData[]) => [prev[0].updateAnalysis(analysis)]))
             }}
             cancel={() => setShowNewUpload(false)} />
           : <></>}

To run:

  • npm install
  • npm run dev

Tell me if you need any more info :)

GregCornis avatar Aug 20 '25 09:08 GregCornis

@fs-eire do you mind having a look or telling me who I should ask ?

GregCornis avatar Sep 30 '25 11:09 GregCornis

remove 'stale'.

fs-eire avatar Oct 30 '25 18:10 fs-eire