Skip to content

Onnxruntime initialization breaks in OpenCode Desktop #195

Description

@Treeed

Short description

globalThis[Symbol.for("onnxruntime")] injection breaks @huggingface/transformers device initialization in Electron

What happened?

This issue was written by an LLM at my direction. I verified its findings and this full text myself.

Environment:

  • @cortexkit/opencode-magic-context v0.29.1
  • @huggingface/transformers v4.2.0
  • onnxruntime-web v1.26.0-dev.20260416
  • OpenCode Desktop v1.17.11

I'm using OpenCode Desktop and I encountered this issue. When running /ctx-embed start I get:

[magic-context] could not resolve local onnxruntime-web/dist, falling back to default WASM paths: "Package subpath './package.json' is not defined by \"exports\" in C:\\Users\\[username]\\.cache\\opencode\\packages\\@cortexkit\\opencode-magic-context@latest\\node_modules\\onnxruntime-web\\package.json"
18:52:13
general
[magic-context] Electron detected — using onnxruntime-web (WASM) for embeddings (bypasses onnxruntime-node native load)
18:52:13
general
[magic-context] embedding model failed to load: Unsupported device: "cpu". Should be one of: .

Why it breaks:

The injectWasmOrtForElectron() function at dist/index.js:166730 does two things:

  1. Imports onnxruntime-web and stores it as globalThis[Symbol.for("onnxruntime")] (line 166749)
  2. Later, @huggingface/transformers is imported

The problem is in @huggingface/transformers's initialization (transformers.node.mjs:11550-11579). It has three code paths:

var ORT_SYMBOL = Symbol.for("onnxruntime");
if (ORT_SYMBOL in globalThis) {
  ONNX = globalThis[ORT_SYMBOL];
  // supportedDevices stays [] -- NEITHER branch below runs
} else if (apis.IS_NODE_ENV) {
  ONNX = ONNX_NODE;  // real onnxruntime-node import
  supportedDevices.push("dml");  // Windows
  supportedDevices.push("webgpu");
  supportedDevices.push("cpu");
  defaultDevices = ["cpu"];      // <-- this is what should happen
} else {
  // browser/WASM path -- also skipped
}

Because magic-context pre-populates globalThis[Symbol.for("onnxruntime")] before the import, transformers takes the first branch -- the ORT backend is set but supportedDevices stays [] and defaultDevices stays undefined.

Meanwhile, DEFAULT_DEVICE is "cpu" (line 13557, because Electron satisfies IS_NODE_ENV). When the pipeline is created at line 166890 without an explicit device option, transformers selects "cpu", calls deviceToExecutionProviders("cpu"), it checks supportedDevices.includes("cpu") -- [] doesn't include "cpu" -- and throws.

The first error (WASM path resolution) is a secondary symptom: requireFn.resolve("onnxruntime-web/package.json") fails because onnxruntime-web has an exports field that doesn't expose ./package.json. It's caught and falls back, but the device error was already inevitable regardless.


The fix:

For now I just removed one line in dist/index.js:

-    globalThis[Symbol.for("onnxruntime")] = ortWeb;

Without the globalThis symbol, transformers takes the normal Node.js path, imports onnxruntime-node (its own dependency), populates supportedDevices with ["dml", "webgpu", "cpu"], and embeddings work correctly.

Diagnostics

Plugin version

0.29.1

OpenCode version

OpenCode Desktop v1.17.11

Platform

Windows x64

Client

OpenCode Desktop

Log output (optional)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions