Skip to content

[4.0.0-next.3] CDN wasmPaths breaks local dev servers (CORS Worker construction error) #1527

@AdrianBesleaga

Description

@AdrianBesleaga

System Info

  • @huggingface/transformers@4.0.0-next.3
  • onnxruntime-web@1.25.0-dev
  • Vite 7.3.1
  • Chrome (latest)
  • macOS

Environment/Platform

  • Website/web-app
  • Browser extension
  • Server-side (e.g., Node.js, Deno, Bun)
  • Desktop app (e.g., Electron)
  • Other (e.g., VSCode extension)

Description

In v4, backends/onnx.js unconditionally sets wasmPaths to cdn.jsdelivr.net:

onnxEnv.wasm.wasmPaths = `https://cdn.jsdelivr.net/npm/onnxruntime-web@${ORT_VERSION}/dist/`;

This causes onnxruntime-web to construct Workers from CDN URLs, which browsers block with a CORS error when the page is served from localhost (or any non-CDN origin):

Failed to construct 'Worker': Script at 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.25.0-dev/dist/ort-wasm-simd-threaded.asyncify.mjs'
cannot be accessed from origin 'http://localhost:5175'.

Additionally, even when serving the ORT files locally, the COEP requirement (Cross-Origin-Embedder-Policy: require-corp) for SharedArrayBuffer means ALL sub-resources need proper Cross-Origin-Resource-Policy headers — which CDN-served files don't have in a local dev context.

v3 behavior (worked correctly)

v3.x did not set wasmPaths, allowing onnxruntime-web to resolve WASM files and Worker scripts relative to the importing script. Bundlers like Vite serve these naturally from localhost, so everything was same-origin — no CORS issues.

Suggested Fix

Only default to CDN wasmPaths if the user hasn't already configured a custom path and the environment isn't a local dev server:

// Only default to CDN if user hasn't overridden and not on localhost
if (!onnxEnv.wasm.wasmPaths) {
    const isLocalDev = typeof location !== 'undefined' &&
        (location.hostname === 'localhost' || location.hostname === '127.0.0.1');
    if (!isLocalDev) {
        onnxEnv.wasm.wasmPaths = `https://cdn.jsdelivr.net/npm/onnxruntime-web@${ORT_VERSION}/dist/`;
    }
}

Or, better yet: revert to v3 behavior and let onnxruntime-web resolve paths naturally. Only use CDN as an explicit opt-in via env.backends.onnx.wasm.wasmPaths.

Current Workaround

Override wasmPaths after import and serve ORT dist files locally (e.g., via vite-plugin-static-copy):

import { env } from '@huggingface/transformers';

// Point to locally-served ORT files instead of CDN
env.backends.onnx.wasm.wasmPaths = '/ort/';

Vite config (using vite-plugin-static-copy):

import { viteStaticCopy } from 'vite-plugin-static-copy';

// Also need cross-origin isolation headers for SharedArrayBuffer
function crossOriginIsolation() {
    return {
        name: 'cross-origin-isolation',
        configureServer(server) {
            server.middlewares.use((_req, res, next) => {
                res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
                res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
                res.setHeader('Cross-Origin-Resource-Policy', 'same-origin');
                next();
            });
        },
    };
}

export default defineConfig({
    plugins: [
        crossOriginIsolation(),
        viteStaticCopy({
            targets: [{ src: '<path-to-onnxruntime-web>/dist/*', dest: 'ort' }],
        }),
    ],
});

Reproduction

  1. Create a Vite project
  2. Install @huggingface/transformers@4.0.0-next.3
  3. In a Web Worker, run:
import { AutoModelForVision2Seq, env } from '@huggingface/transformers';

env.allowLocalModels = false;
env.useBrowserCache = true;

const model = await AutoModelForVision2Seq.from_pretrained(
    'HuggingFaceTB/SmolVLM-500M-Instruct',
    { dtype: 'q4f16', device: 'webgpu' }
);
  1. Browser console shows: Failed to construct 'Worker' CORS error

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions