WasiProcess.run() never settles when instantiate fails or _start traps (e.g. missing fd_fdstat_set_rights import)
Maintainers usually reply within 1 day
@dbaeumer is already working on this.
Since Oct 6, 2026.
Assessment
This issue has not been assessed yet.
Description
Summary
WasiProcess.run() never settles (no result, no rejection, no visible error) when the worker running the module throws before or while executing _start. Two ways this was observed:
- A module that imports
wasi_snapshot_preview1.fd_fdstat_set_rights. The host does not implement it, soWebAssembly.instantiatethrows aLinkError. - A module whose
_starttraps (e.g. anunreachableinstruction, which is whatabort(), a failedassert, orstd::terminatecompile to).
Both hang process.run() forever. (1) is the missing import; (2) and (1) share the same root cause: errors in the main worker are only logged, never reported back to the extension host.
Impact
- Any wasm program that imports
fd_fdstat_set_rightshangs on launch with no diagnostic. We hit this in the wild: linking a C++ program withwasm-ld --no-gc-sectionskeeps every libc object, so the module imports the fullwasi_snapshot_preview1set (~45 functions) instead of the usual ~6, includingfd_fdstat_set_rights. The program itself is fine (it builds and prints correctly under Node'snode:wasi). - Any trapping program (
abort(), failedassert, uncaught exception with-fno-exceptions,std::terminate, out-of-bounds access, stack overflow) leavesrun()pending forever. Embedders such as terminals, test runners and build tools wait indefinitely and have no way to tell a hang from a long computation. - Because the error appears only in the worker's console, it is very hard to diagnose from the extension side.
Root cause (from reading the source at 6714478fe3b73855355403f40e70c0b950d0128e)
Missing import. fd_fdstat_set_rights does not appear anywhere under wasm-wasi-core/src (grep -rn set_rights wasm-wasi-core/src finds nothing). common/host.ts builds the import object with fd_fdstat_get and fd_fdstat_set_flags but no fd_fdstat_set_rights, so the property is undefined and instantiation fails with:
LinkError: WebAssembly.instantiate(): Import #0 "wasi_snapshot_preview1" "fd_fdstat_set_rights": function import requires a callable
I bisected this empirically: I generated one tiny module per wasi_snapshot_preview1 import used by the --no-gc-sections build (all of them), each importing exactly one function and exporting an empty _start, and ran each with createProcess(...).run() and a timeout. all others ran and exited with 0; only fd_fdstat_set_rights hung.
Swallowed error. In web/mainWorker.ts, handleMessage does await WebAssembly.instantiate(module, imports) and then calls _start with no try/catch. The exception rejects the promise returned by handleMessage, and the caller in web/connection.ts only does .catch(RAL().console.error). Meanwhile this._done is never resolved or rejected, so main() stays blocked on await connection.done() and never posts workerDone. On the extension-host side, run() only resolves on proc_exit or workerDone (common/process.ts / web/process.ts), and nothing listens for worker errors, so it waits forever.
web/threadWorker.ts has the same unguarded instantiate / wasi_thread_start path, so the same hang is expected for thread workers (I did not test threads).
Reproduction (no toolchain needed)
Module (WAT):
(module
(import "wasi_snapshot_preview1" "fd_fdstat_set_rights" (func))
(memory (export "memory") 1)
(func (export "_start")))
(Signature is irrelevant for the repro; the real import is (i32 i64 i64) -> i32. A host function type mismatch is not checked for JS-provided imports, and the missing property is what fails.)
From a VS Code web extension with ms-vscode.wasm-wasi-core installed:
import { Wasm } from '@vscode/wasm-wasi';
const wasm = await Wasm.load();
const module = await WebAssembly.compile(bytes); // the module above
const process = await wasm.createProcess('t', module, { stdio: { out: { kind: 'pipeOut' }, err: { kind: 'pipeOut' } } });
await process.run(); // never resolves or rejects
Trap variant: replace the body with (module (memory (export "memory") 1) (func (export "_start") unreachable)); run() also never settles.
Real-world trigger: compile a hello-world with a wasm32-wasip1 clang, then link with wasm-ld ... --no-gc-sections. The resulting module imports fd_fdstat_set_rights (plus sock_accept, fd_advise, ...); it runs fine under Node's node:wasi.
Tested with wasm-wasi-core 1.0.2 (as loaded by @vscode/test-web in Chromium), source at the commit above.
Suggested fix
- Add
fd_fdstat_set_rightsto the host and service layers, returningErrno.nosys(it is part ofwasi_snapshot_preview1; a no-op/nosysstub is enough for programs that merely import it). - In
mainWorker.ts(andthreadWorker.ts), wrap instantiate and_startin try/catch; on failure post an error message back (or at least still resolve_donesoworkerDoneis posted) so thatrun()rejects or returns a non-zero exit code instead of hanging. For a trap, a conventional exit code with the error written to stderr would match what other WASI hosts do.
Disclosure
This issue was detected, root-caused and written up by Claude (an AI coding assistant, Claude Code) while working in a user's repository, and is filed by Claude with the explicit consent of the repository owner (Ambeco). The reproduction and the bisect were run for real in Chromium via @vscode/test-web; the root-cause analysis comes from reading the source, and the hang mechanism was not additionally confirmed with instrumentation inside the worker.
- Dominant language
- TypeScript
- Stars
- 456
- Forks
- 42
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 11
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from microsoft/vscode-wasm
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
microsoft/vscode-wasm#249 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 3/5 1-2 days Newbie friendliness 55/100
microsoft/vscode-wasm#244 · 2 reactions ·
Maintainers usually reply within 1 day
-
bug
Difficulty 3/5 1-2 days Newbie friendliness 35/100
microsoft/vscode-wasm#240 ·
Maintainers usually reply within 1 day
-
feature-request
Difficulty 5/5 Over a week Newbie friendliness 28/100
microsoft/vscode-wasm#235 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 3/5 1-2 days Newbie friendliness 25/100
microsoft/vscode-wasm#217 · 3 comments · 2 reactions ·
Maintainers usually reply within 1 day
All issues in microsoft/vscode-wasm
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
better-auth/better-auth#12132 · 1 reaction ·
Maintainers usually reply within 1 day
-
o8 next debug build aborts on Glass to Dark appearance switch (nil identifier messaged before check)Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
hurttlocker/o8#5112 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
webrecorder/wabac.js#386 ·
-
needs-triage
Difficulty 1/5 1-3 hours Newbie friendliness 92/100
agent-of-empires/agent-of-empires#5098 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day