V8 / WASM engine bump — steps to unblock the exnref CI failures (PR #129396)
PR dotnet/runtime#129396 ([browser] upgrade
wasm exceptions) switches the WASM exception-handling model to the exnref proposal. The
V8/JS engine installed on the CI WASM queues (V8 15.0.243, via jsvu) does not recognize the
--experimental-wasm-exnref flag, so the runtime's startup feature check asserts and aborts
before any test runs. This single root cause produces three distinct CI failures.
The failures this addresses
Failure 1 — Mono runtime tests fail to start under V8
Leg: browser-wasm linux Release AllSubsets_Mono_RuntimeTests monointerpreter.
65 of 66 work items fail, every one with exitCode 71 (XHarness GENERAL_FAILURE),
failureCategory: InfrastructureError. Console evidence:
JS_ENGINE_ARGS=--engine-arg=--stack-trace-limit=1000 --engine-arg=--experimental-wasm-exnref
info: 15.0.243
info: Warning: unknown flag --experimental-wasm-exnref.
info: Try --help for options
info: MONO_WASM: Assert failed: This browser/engine doesn't support WASM exception handling.
Please use a modern version. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms
info: Error: Top-level await promise never resolved
fail: Application has finished with exit code 1 but 0 was expected
XHarness exit code: 71 (GENERAL_FAILURE)
Failure 2 — Trimming tests fail identically under V8
Leg: dotnet-linker-tests · browser-wasm linux release Runtime_Release → task
Run Trimming Tests. Ends with 320 Error(s); every trimmed app launched via run-v8.sh
fails the same way across System.Runtime, Microsoft.Extensions.Http, and System.Text.Json:
EXEC : error : unknown flag --experimental-wasm-exnref.
EXEC : error : Top-level await promise never resolved
EXEC : error : Assert failed: This browser/engine doesn't support WASM exception handling.
Please use a modern version. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms
Failure 3 — wasm-perf MicroBenchmarks fail identically under V8
Leg: runtime-wasm-perf · Performance micro wasm v8 linux x64 perfviper net11.0 → task
Send job to Helix (Unix). The perf Helix job crashes at startup:
[INFO] MONO_WASM: Assert failed: This browser/engine doesn't support WASM exception handling.
Please use a modern version. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms
[INFO] main.mjs:294: Error: Top-level await promise never resolved
[INFO] ProcessData operation is interrupted by EarlyProcessExit.
[INFO] No Workload Results were obtained from the run.
Why the engine matters and where it comes from
| Failure |
Leg |
Where the engine comes from |
| 1 |
AllSubsets_Mono_RuntimeTests monointerpreter (browser-wasm) |
V8 inside the Helix webassembly docker image (jsvu) |
| 2 |
dotnet-linker-tests Run Trimming Tests |
same Helix webassembly docker image, via run-v8.sh |
| 3 |
Performance micro wasm v8 linux x64 |
V8 inside the perf WASM container (jsvu) |
The engine V8 binary that runs the tests is not downloaded from BrowserVersions.props on
Helix — it is baked into the *-helix-webassembly-amd64 container images (installed there with
jsvu). That is why "the image with the latest V8 doesn't exist in the feed yet" blocks us:
the runtime repo only references those images by digest, it does not build them.
Prerequisite (upstream, NOT in dotnet/runtime)
The new container image carrying a V8 that supports exnref must first be built and published by
dotnet/dotnet-buildtools-prereqs-docker.
- The Dockerfiles for the
*-helix-webassembly-amd64 (and the windows
*-helix-webassembly-amd64) images install V8 via jsvu. Bump the V8/jsvu version there.
- Once merged, the build publishes new images to
mcr.microsoft.com/dotnet-buildtools/prereqs
with new sha256 digests. Capture those digests — every step below pins by digest.
Until those images exist in the feed (MCR), the runtime-side changes below cannot be made
(there is no digest to point at). The steps assume the images now exist.
Steps once the new image exists in the feed
1. Update the Helix queue image digests (runs the tests — fixes Failures 1, 2, 3)
Replace the old @sha256:… digests with the new ones for every *-helix-webassembly-* reference.
eng/pipelines/helix-platforms.yml references the same
images without a pinned digest, so it floats to latest and usually needs no change. If it
ever pins a digest, update it too.
2. Update the WASM build container digest (fixes Failure 2's build, and any build-time V8 use)
3. Update the perf WASM engine (fixes Failure 3)
The wasm-perf leg does not use the V8 baked into the container. Instead,
dotnet/performance scripts/run_performance_job.py
reads the version straight from this repo's
eng/testing/BrowserVersions.props (linux_V8Version,
truncated to major.minor.patch) and then installs that exact build with jsvu at job time:
jsvu --os=linux64 v8@<linux_V8Version>
export V8_ENGINE_PATH=~/.jsvu/bin/v8-<linux_V8Version>
So bumping linux_V8Version in eng/testing/BrowserVersions.props
(step 4) is sufficient and authoritative for the perf leg — no change in dotnet/performance is
needed, provided jsvu can resolve the requested V8 version.
4. Bump the pinned V8 version in BrowserVersions.props (required for the perf leg; also local-dev)
This is the authoritative version for the perf leg (see step 3, consumed via jsvu) and for
local runs / any leg that downloads V8 instead of using the container. Bump it so the engine is
exnref-capable:
This version is consumed by eng/testing/wasm-provisioning.targets
(DownloadAndInstallV8), which downloads from
https://storage.googleapis.com/chromium-v8/official/canary/v8-<platform>-rel-<version>.zip.
Pick a V8 build that ships exnref without the experimental flag. The UpdateChromeVersions
task (src/tasks/WasmBuildTasks/UpdateChromeVersions.cs)
can auto-bump this file from Chromium Dash.
Files to change — summary
Validation
After the digests are updated, re-run the affected pipelines:
/azp run runtime
/azp run runtime-llvm
/azp run dotnet-linker-tests
/azp run runtime-wasm-perf
Confirm the engine banner in a WASM work-item log shows the new V8 version and that
--experimental-wasm-exnref is no longer reported as an unknown flag (or, once the engine
enables exnref by default, that the flag is dropped from
eng/testing/WasmRunnerTemplate.sh /
eng/testing/WasmRunnerTemplate.cmd and the various sample
RunScriptCommands).
V8 / WASM engine bump — steps to unblock the exnref CI failures (PR #129396)
PR dotnet/runtime#129396 ([browser] upgrade
wasm exceptions) switches the WASM exception-handling model to the exnref proposal. The
V8/JS engine installed on the CI WASM queues (V8 15.0.243, via
jsvu) does not recognize the--experimental-wasm-exnrefflag, so the runtime's startup feature check asserts and abortsbefore any test runs. This single root cause produces three distinct CI failures.
The failures this addresses
Failure 1 — Mono runtime tests fail to start under V8
Leg:
browser-wasm linux Release AllSubsets_Mono_RuntimeTests monointerpreter.65 of 66 work items fail, every one with
exitCode 71(XHarnessGENERAL_FAILURE),failureCategory: InfrastructureError. Console evidence:Failure 2 — Trimming tests fail identically under V8
Leg: dotnet-linker-tests ·
browser-wasm linux release Runtime_Release→ taskRun Trimming Tests. Ends with 320 Error(s); every trimmed app launched via
run-v8.shfails the same way across
System.Runtime,Microsoft.Extensions.Http, andSystem.Text.Json:Failure 3 — wasm-perf MicroBenchmarks fail identically under V8
Leg: runtime-wasm-perf ·
Performance micro wasm v8 linux x64 perfviper net11.0→ taskSend job to Helix (Unix). The perf Helix job crashes at startup:
Why the engine matters and where it comes from
AllSubsets_Mono_RuntimeTests monointerpreter(browser-wasm)Run Trimming Testsrun-v8.shPerformance micro wasm v8 linux x64The engine V8 binary that runs the tests is not downloaded from
BrowserVersions.propsonHelix — it is baked into the
*-helix-webassembly-amd64container images (installed there withjsvu). That is why "the image with the latest V8 doesn't exist in the feed yet" blocks us:the runtime repo only references those images by digest, it does not build them.
Prerequisite (upstream, NOT in dotnet/runtime)
The new container image carrying a V8 that supports
exnrefmust first be built and published bydotnet/dotnet-buildtools-prereqs-docker.
*-helix-webassembly-amd64(and the windows*-helix-webassembly-amd64) images install V8 viajsvu. Bump the V8/jsvuversion there.mcr.microsoft.com/dotnet-buildtools/prereqswith new
sha256digests. Capture those digests — every step below pins by digest.Steps once the new image exists in the feed
1. Update the Helix queue image digests (runs the tests — fixes Failures 1, 2, 3)
Replace the old
@sha256:…digests with the new ones for every*-helix-webassembly-*reference.ubuntu-26.04-helix-webassembly-amd64@sha256:…(multiple lines)windowsservercore-ltsc2025-helix-webassembly-amd64@sha256:…and
windowsservercore-ltsc2022-helix-webassembly@sha256:…ubuntu-26.04-helix-webassembly-amd64@sha256:…(open + internal queues)2. Update the WASM build container digest (fixes Failure 2's build, and any build-time V8 use)
azurelinux-3.0-net11.0-webassembly-amd64@sha256:…3. Update the perf WASM engine (fixes Failure 3)
The wasm-perf leg does not use the V8 baked into the container. Instead,
dotnet/performance
scripts/run_performance_job.pyreads the version straight from this repo's
eng/testing/BrowserVersions.props (
linux_V8Version,truncated to
major.minor.patch) and then installs that exact build withjsvuat job time:So bumping
linux_V8Versionin eng/testing/BrowserVersions.props(step 4) is sufficient and authoritative for the perf leg — no change in dotnet/performance is
needed, provided
jsvucan resolve the requested V8 version.4. Bump the pinned V8 version in BrowserVersions.props (required for the perf leg; also local-dev)
This is the authoritative version for the perf leg (see step 3, consumed via
jsvu) and forlocal runs / any leg that downloads V8 instead of using the container. Bump it so the engine is
exnref-capable:linux_V8Version(perf leg + local Linux),macos_V8Version,win_V8Version(currently15.1.103)This version is consumed by eng/testing/wasm-provisioning.targets
(
DownloadAndInstallV8), which downloads fromhttps://storage.googleapis.com/chromium-v8/official/canary/v8-<platform>-rel-<version>.zip.Pick a V8 build that ships
exnrefwithout the experimental flag. TheUpdateChromeVersionstask (src/tasks/WasmBuildTasks/UpdateChromeVersions.cs)
can auto-bump this file from Chromium Dash.
Files to change — summary
@sha256:digests@sha256:digests@sha256:digest*_V8Version— drives local provisioning and the perf leg (Failure 3) via jsvuValidation
After the digests are updated, re-run the affected pipelines:
Confirm the engine banner in a WASM work-item log shows the new V8 version and that
--experimental-wasm-exnrefis no longer reported as an unknown flag (or, once the engineenables
exnrefby default, that the flag is dropped fromeng/testing/WasmRunnerTemplate.sh /
eng/testing/WasmRunnerTemplate.cmd and the various sample
RunScriptCommands).