Repository navigation
Blazor WebAssembly debugger: decode_ptr_id assertion at startup, BPs solid-red but never hit — VS2026 18.6.0 + dn10 SDK 10.0.300 (similar to #121738 which is reportedly fixed) #128407
Description
Description
VS2026 18.6.0 paired with dn10 SDK 10.0.300 produces an unusable debug experience for a large Standalone Blazor WebAssembly app. The symptoms closely match those reported in #121738, but that issue's final comment indicates a fix shipped in VS 18.3 Insiders 2 — I'm on 18.6.0 (later) and reproducing, so this looks like either a regression or a closely related-but-distinct issue.
A vanilla dotnet new blazorwasm -f net10.0 project on the same machine debugs perfectly. So VS + SDK + browser are functional in isolation; something about my (large, ABP 10.3-based, ~100 project references) solution amplifies the problem.
Reproduction Steps
I do not currently have a minimal repro — the issue appears to be sensitive to solution scale (~100 project refs vs vanilla's ~5). Steps I take when reproducing locally:
- Open the solution in VS2026 18.6.0
- F5 multi-startup (tenant API + host API + tenant WASM client + host WASM client)
- Once the tenant WASM app loads in the browser, set a breakpoint in any reachable C# code (e.g. a Razor page's
OnInitializedAsync, a button click handler, an ABP module'sConfigureServices) - Trigger the path
I'm willing to work toward a minimal repro if a maintainer can confirm interest — the scale-dependence makes it non-trivial.
Expected behavior
- Breakpoints bind (solid red) and hit when the underlying code executes
- No
[MONO] * Assertionin the browser console when setting breakpoints - No spurious JS-side breaks at startup
- Stopping the debug session completes promptly and releases all file handles
Actual behavior
Three persistent symptoms:
-
"Play-button plague" — many JS-side breakpoints fire at WASM startup; user has to click play repeatedly before VS hooks up.
-
Managed breakpoints never hit. VS shows them solid-red (PDB binding succeeds at IDE level) but they're inert at runtime. Stack trace captured in browser console when setting a BP:
[MONO] * Assertion at /__w/1/s/src/runtime/src/mono/mono/component/debugger-agent.c:2043, condition `<disabled>' not met at Mc (logging.ts:125:60) at dotnet.native.wasm.wasm_trace_logger at dotnet.native.wasm.eglib_log_adapter at dotnet.native.wasm.monoeg_g_logv_nofree at dotnet.native.wasm.monoeg_assertion_message at dotnet.native.wasm.mono_assertion_message at dotnet.native.wasm.mono_assertion_message_disabled at dotnet.native.wasm.decode_ptr_id (debugger-agent.c:2043) at dotnet.native.wasm.mono_process_dbg_packet at dotnet.native.wasm.mono_wasm_send_dbg_command at ccall (dotnet.native.js:6715) at mono_wasm_send_dbg_command (debug.ts:94) at (anonymous) (eval.cdp:1) at (anonymous) (debug.ts:33) at configureEmscriptenStartup (startup.ts:340)Path:
startup.ts:340→onRuntimeInitialized→mono_wasm_runtime_ready(which executesdebugger;whenglobalThis.dotnetDebuggeris set) → VS catches the break → CDPevalcallsmono_wasm_send_dbg_commandwith aptr_idthat fails theg_assert (id > 0 && GINT_TO_UINT(id) <= ids[type]->len)check indecode_ptr_id. The agent's state appears corrupted from boot; subsequent BPs are silently inert.Sometimes accompanied by
program exited (with status: 1), but keepRuntimeAlive() is setshortly after. -
Stop-debug hangs, eventually requiring "force stop"; leaves a persistent file lock on project-ref DLLs held by
devenv.exe(e.g.MyApp.Components.Shared.dll), preventing the next build.
Regression?
Likely. Closest matching issue #121738 was reportedly fixed in VS 18.3 Insiders 2, but I'm reproducing on 18.6.0. Behavioural notes:
- I cannot test prior VS2026 versions easily but did upgrade to 18.6.0 mid-investigation with no change in symptoms.
- The app debugged correctly under VS 2022 / .NET 8 prior to our dn8 → dn10 upgrade. So the regression entered with the dn10 SDK + VS2026 combination.
- A colleague on the same codebase using Rider does not see any of these symptoms — different debug protocol adapter, so the problem looks specific to the VS WASM debug adapter.
Known Workarounds
None that I have found that retain working managed debug. Things tried and confirmed not to fix it:
- Disable "Enable JavaScript debugging for ASP.NET (Chrome, Edge and IE)" (the documented workaround from Blazor WebAssembly (.NET 10) debug crash: Mono assertion “should not be reached” (class-accessors.c:93) when hitting HttpClient in component; JS debug adapter exits 0xffffffff #121738) — already off in my VS and was off long before symptoms started.
- Toggle
WasmBuildNative,OverrideHtmlAssetPlaceholders,<HotReloadEnabled>,WasmFingerprintAssets,BlazorFingerprintBlazorJs,BlazorWebAssemblyLoadAllGlobalizationDataindividually. - Disable "Just My Code".
- Disable / comment out our custom service worker registration (the dev SW is a passthrough with no
fetchhandler, so this was expected to be inert; confirmed). - "Nuclear" cache reset: close VS, kill all helper processes,
dotnet build-server shutdown, delete.vs/, allbin/andobj/solution-wide, VSComponentModelCacheat%LOCALAPPDATA%\Microsoft\VisualStudio\18.0_*\ComponentModelCache,dotnet restore, browser SW unregister + clear site data. No effect. - VS upgrade from earlier to 18.6.0.
Removing inspectUri from launchSettings.json suppresses the symptoms but only by disabling the managed debug channel entirely — i.e. no debug at all, not a real workaround.
The only thing that works in practice: switch to Rider.
Configuration
- VS: Visual Studio 2026 18.6.0
- SDK: 10.0.300 (runtime 10.0.8)
- App: Standalone Blazor WebAssembly, ABP Framework 10.3, ~100 project references
- OS: Windows 11
- Browser: Chrome (latest stable). Symptom reproduces in Edge too.
Other information
Vanilla comparator on the same machine: dotnet new blazorwasm -f net10.0 in C:\Temp\vanilla-dn10-wasm, opened in VS, F5 — BPs bind AND hit, no play-button plague, no decode_ptr_id assertion, no DLL locks. So this is specifically an interaction between something in the large solution and the VS2026 WASM debug adapter.
Property diff between my csproj and the vanilla template (just the properties I set that vanilla doesn't): BlazorWebAssemblyLoadAllGlobalizationData=true, ServiceWorkerAssetsManifest, WasmFingerprintAssets=false, BlazorFingerprintBlazorJs=false, WasmBuildNative=true, EmitCompilerGeneratedFiles=true. Toggling each individually did not move the needle.
Hypothesis (best guess from outside): the dn10 WASM debug agent's ids[type] array isn't fully populated at the moment VS issues its startup debug commands via CDP eval, leading to out-of-bounds ptr_id lookups in decode_ptr_id. Large solutions may load assemblies more slowly relative to VS's attach pacing, exposing the race. The assertion silently corrupts agent state, and all subsequent BP-set commands then fail to wire through to the runtime.
Happy to provide more diagnostic info, build logs, launchSettings, or work toward a minimal repro if useful — please flag what would be most helpful.
Activity
jon001 commentedon May 26, 2026
Follow-up — most of it was local, but one VS-specific gap remains
git bisecton 2026-05-25 traced the visible symptoms (BPs not hitting, "play-button plague" at startup, stop-debug hangs + DLL locks) to a single commit in our own repo — so that part was a local bug, not the VS or dn10 SDK issue I initially reported. But a residual problem remains where VS can't evaluate local variables at WASM breakpoints, and a colleague on the same codebase using JetBrains Rider has confirmed Rider doesn't have it. That part looks like a genuine VS-side gap.What was local (now fixed in our repo)
The first-bad commit added the following pair of MSBuild properties to our
.csproj, unconditionally, to work around static-host deploy issues (Azure Static Web Apps / nginx serving canonical-named WASM assets):These tell the SDK to emit canonical-named WASM framework assets (e.g.
dotnet.wasminstead ofdotnet.<hash>.wasm). This was a workaround to some still unresolved issues with the deployed instances serving fingerprinted resources.Observed consequence with this configuration, on every Debug F5 in VS:
.csBPs show solid-red but never actually trigger when their code executesdevenv.exeThe
<disabled>condition string is stripped in release builds of Mono; in the dn10 release/10.0 source, line 2043 ofdebugger-agent.cisg_assert (id > 0 && GINT_TO_UINT(id) <= ids [type]->len);insidedecode_ptr_id.I don't have a verified mechanistic explanation for why setting
WasmFingerprintAssets=falseand/orBlazorFingerprintBlazorJs=falseproduces these symptoms — that would require reading the VS WASM debug proxy and Mono debug-agent code paths in detail. What I can say is that the bisect signal is strong: every commit before the property was added has working debug; every commit after, with no other relevant changes, doesn't. And removing the unconditional setting (see below) fixes all the visible symptoms.Fix on our side: make both properties Release-only so Debug builds keep the SDK default (
true) and Release/publish gets the canonical-names workaround for static hosts:Verified after fix: Debug F5 builds debug normally (BPs hit, no console assertion, fast stop-debug, no DLL locks); Release builds still emit canonical-named assets, so the static-host deploys aren't regressed.
Secondary local bug (also fixed)
Independently, our csprojs had ~80 redundant
<AdditionalFiles Include="...razor" />entries that explicitly registered razor files as Razor source generator inputs. The Blazor WASM SDK also auto-discovers.razorfiles for the same purpose, so the Razor SG saw each file twice and crashed:This crashed the entire Razor source generator for the project, surfacing as "Razor Diagnostics Feature is currently unavailable due to an internal error" in the VS info bar, and made
.razorBPs unsettable. The duplicate entries pre-existed our dn10 upgrade; I don't know whether the older Razor SG handled them differently or whether they were silently broken for longer than we noticed. Either way, fix: remove all razor<AdditionalFiles>entries; SDK default discovery does the job.What still isn't right — and looks VS-specific
With the local fixes applied, BPs in C# and Razor files both hit cleanly. But local variable evaluation at any WASM breakpoint still fails, in both the Locals panel and Watch:
Affects:
enumProperties,filter, etc.) — locals declared in the current methodthisitselfthis.SomeRealField,this.SomeProperty)Static analysis works — if I type a bogus path in Watch like
this.NonexistentMember, VS correctly reportserror CS1061: 'CertificateList' does not contain a definition for 'NonexistentMember'. So assembly/PDB metadata is reaching VS at some level; only the runtime evaluation step (over CDP) appears to fail.Comparator that I think makes this VS-specific — and the reason I'm leaving this issue open as data rather than just closing it: a colleague on the same codebase using JetBrains Rider can inspect locals at WASM breakpoints normally. Same branch (post our local fixes), same
WasmBuildNative=true(which our project requires because Bit.Besql links e_sqlite3.a natively), same Bit.Besql, same SDK. Rider's WASM debug implementation evaluates locals; VS's doesn't.If Rider can resolve locals on this configuration, the data is reachable from outside the WASM runtime — so what's missing isn't in the SDK or the runtime but in how VS specifically interrogates it. Might be a known limitation, might be a fileable separate bug; flagging here rather than guessing.
Configuration
Happy to provide diagnostic info, a build log, repro details, or work toward a minimal repro if useful for the eval-failure piece.
pavelsavara commentedon Jun 1, 2026
@jon001
Fingerprints are cache busting technique.
I suspect you are loading previous version of
dotnet.native.wasmfrom some earlier build of your app from stale (browser) HTTP cache.Try
cleancommand.Then please report back
jon001 commentedon Jun 1, 2026
@pavelsavara Thanks for the reply. Of those, I can answer all but one immediately:
I doubt it's a stale dotnet.native.wasm but I'll try another machine when I have a minute.
jon001 commentedon Jun 1, 2026
Oh, I should add that a colleague (until recently the only other non-Rider using colleage) was/is experiencing the same problem in the same codebase, so perhaps that covers the "other machine" test.
1 remaining item
pavelsavara commentedon Jun 1, 2026
Now we need some steps to reproduce, otherwise this is not actionable.
jon001 commentedon Jun 1, 2026
That will be the problem I think. We've already invested a lot of time locating the specific change that broke Visual Studio, and the boundary between working VS WASM debug and us is very unclear. This is a large project with many dependencies so creating a minimal repro would most likely be a lot of work.
It's hard to justify that to the team when the workaround is "just use Rider".
Perhaps Claude can build me something - I'll ask!
jon001 commentedon Jun 23, 2026
Follow-up — most of it was local, but one VS-specific gap remains
git bisecton 2026-05-25 traced the visible symptoms (BPs not hitting, "play-button plague" at startup, stop-debug hangs + DLL locks) to a single commit in our own repo — so that part was a local bug, not the VS or dn10 SDK issue I initially reported. But a residual problem remains where VS can't evaluate local variables at WASM breakpoints, and a colleague on the same codebase using JetBrains Rider has confirmed Rider doesn't have it. That part looks like a genuine VS-side gap.What was local (now fixed in our repo)
The first-bad commit added the following pair of MSBuild properties to our
.csproj, unconditionally, to work around static-host deploy issues (Azure Static Web Apps / nginx serving canonical-named WASM assets):These tell the SDK to emit canonical-named WASM framework assets (e.g.
dotnet.wasminstead ofdotnet.<hash>.wasm). This was a workaround to some still unresolved issues with the deployed instances serving fingerprinted resources.Observed consequence with this configuration, on every Debug F5 in VS:
.csBPs show solid-red but never actually trigger when their code executesdevenv.exeThe
<disabled>condition string is stripped in release builds of Mono; in the dn10 release/10.0 source, line 2043 ofdebugger-agent.cisg_assert (id > 0 && GINT_TO_UINT(id) <= ids [type]->len);insidedecode_ptr_id.I don't have a verified mechanistic explanation for why setting
WasmFingerprintAssets=falseand/orBlazorFingerprintBlazorJs=falseproduces these symptoms — that would require reading the VS WASM debug proxy and Mono debug-agent code paths in detail. What I can say is that the bisect signal is strong: every commit before the property was added has working debug; every commit after, with no other relevant changes, doesn't. And removing the unconditional setting (see below) fixes all the visible symptoms.Fix on our side: make both properties Release-only so Debug builds keep the SDK default (
true) and Release/publish gets the canonical-names workaround for static hosts:Verified after fix: Debug F5 builds debug normally (BPs hit, no console assertion, fast stop-debug, no DLL locks); Release builds still emit canonical-named assets, so the static-host deploys aren't regressed.
Secondary local bug (also fixed)
Independently, our csprojs had ~80 redundant
<AdditionalFiles Include="...razor" />entries that explicitly registered razor files as Razor source generator inputs. The Blazor WASM SDK also auto-discovers.razorfiles for the same purpose, so the Razor SG saw each file twice and crashed:This crashed the entire Razor source generator for the project, surfacing as "Razor Diagnostics Feature is currently unavailable due to an internal error" in the VS info bar, and made
.razorBPs unsettable. The duplicate entries pre-existed our dn10 upgrade; I don't know whether the older Razor SG handled them differently or whether they were silently broken for longer than we noticed. Either way, fix: remove all razor<AdditionalFiles>entries; SDK default discovery does the job.What still isn't right — and looks VS-specific
With the local fixes applied, BPs in C# and Razor files both hit cleanly. But local variable evaluation at any WASM breakpoint still fails, in both the Locals panel and Watch:
Affects:
enumProperties,filter, etc.) — locals declared in the current methodthisitselfthis.SomeRealField,this.SomeProperty)Static analysis works — if I type a bogus path in Watch like
this.NonexistentMember, VS correctly reportserror CS1061: 'CertificateList' does not contain a definition for 'NonexistentMember'. So assembly/PDB metadata is reaching VS at some level; only the runtime evaluation step (over CDP) appears to fail.Comparator that I think makes this VS-specific — and the reason I'm leaving this issue open as data rather than just closing it: a colleague on the same codebase using JetBrains Rider can inspect locals at WASM breakpoints normally. Same branch (post our local fixes), same
WasmBuildNative=true(which our project requires because Bit.Besql links e_sqlite3.a natively), same Bit.Besql, same SDK. Rider's WASM debug implementation evaluates locals; VS's doesn't.If Rider can resolve locals on this configuration, the data is reachable from outside the WASM runtime — so what's missing isn't in the SDK or the runtime but in how VS specifically interrogates it. Might be a known limitation, might be a fileable separate bug; flagging here rather than guessing.
Forward-isolation attempts (none reproduced the failure)
To rule out specific features of our codebase as the cause, I built a minimal
dotnet new blazorwasm -f net10.0project and progressively layered our app's distinguishing characteristics onto it. Each layer below was added cumulatively and tested with aCounter-like razor component setting a BP and checkingthis/locals in the VS Locals panel:<WasmBuildNative>true</WasmBuildNative>+Microsoft.Data.Sqlite+SQLitePCLRaw.bundle_e_sqlite3(native re-link of the runtime withe_sqlite3.a) — eval still works.Bit.Besqlpackage (the WASM SQLite library we use) — still works.<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>— still works.<ServiceWorkerAssetsManifest>+ a registered service worker — still works.AddApplicationAsync<TModule>(options => options.UseAutofac())+InitializeApplicationAsync— still works.[Inject]properties propagated via_Imports.razor+@implements IDisposableon the component — still works.I also built four standalone variants of the cumulative project, each adding a distinct further dimension:
IHttpClientFactoryinterceptor returning a stubApplicationConfigurationDtofor/api/abp/application-configuration) so the fullInitializeApplicationAsyncruns to completion rather than failing — eval still works.App.razorin the RCL at the same logical path as the main project'sApp.razor— mirrors ourThemes/Basic/App.razorsituation) — eval still works.Counter : ListViewModelComponent<TVm> : ListViewModelComponent<TVm,TVm> : ClikViewModelComponentBase<TVm> : CloudBaseComponent : OwningComponentBase, with ~22[Inject]properties across the chain and theIAsyncDisposable+IDisposableshape — eval still works. (This was our strongest "unusual thing" candidate, because our real components root atOwningComponentBaserather thanComponentBaseand that class manages a privateIServiceScopefield that the debug agent would have to walk when materialisingthis.)So 14 distinct hypotheses tested in isolation, none reproduce. The cause has to be something we haven't been able to construct from scratch — either some specific runtime behaviour of our app, a more exotic combination of conditions, or something more subtle we haven't identified. Forward-isolation appears genuinely exhausted as a method here; the only remaining route to root-cause from our side is reverse-bisection from the real project, which we haven't attempted at scale.
Configuration
Happy to provide diagnostic info, a build log, repro details, or work toward a minimal repro if useful for the eval-failure piece.
dotnet-policy-service commentedon Oct 14, 2026
This issue has been automatically marked
no-recent-activitybecause it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will removeno-recent-activity.