Repository navigation
Main-window WebView2 renderer self-aborts with STATUS_BREAKPOINT (0x80000003): root cause and verified workaround #3200
Description
[Filed by Copilot on behalf of @bghgary]
Originally filed as github/copilot-cli#4492, which was the wrong repo — that one tracks the CLI. Re-filing here with the analysis corrected. Same crash as #2861, #2989, #3019 and #3135; this issue adds the root cause and a verified workaround.
The Copilot desktop app's main-window WebView2 renderer terminates itself with STATUS_BREAKPOINT (0x80000003). The window goes blank and stays blank until manually refreshed, losing any open canvas panel. 23 confirmed occurrences on one machine between 2026-08-13 and 2026-08-24, at roughly one per 3.9 working-hours of app uptime.
Supporting evidence — disassembly, full stack, crash-key table, A/B measurements — is in this gist.
Root cause
A CHECK in Blink's accessibility tree serializer fires during the post-layout phase of a main frame — third_party/blink/renderer/modules/accessibility/ax_block_flow_iterator.cc:184, in AXBlockFlowData::ComputeNeighborOnLine:
case FragmentItem::kText:
case FragmentItem::kGeneratedText:
if (!it->GetLayoutObject()) [[unlikely]] {
// A generated text fragment item may not have a backing LayoutObject.
// For regular text, we expect them to always have one.
CHECK_EQ(it->Type(), FragmentItem::kGeneratedText); // <-- fires
}A fragment item of type kText is reached with a null LayoutObject. The code assumes only generated text can lack one, and Chromium's own TODO three lines below notes the area is not fully understood: "Investigate when an item can be text, but its LayoutObject is not marked as such."
Abridged stack:
<int3> <- the CHECK
blink::AXBlockFlowIterator::PreviousOnLineAsIndex
blink::AXInlineTextBox::NeighboringOnLineWithAXBlockFlowIterator
blink::AXObject::SerializeLineAttributes
blink::AXObject::SerializeInlineTextBox
ui::AXTreeSerializer<...>::SerializeChangedNodes (recursion x8)
blink::AXObjectCacheImpl::SerializeAXUpdatesIfNeeded
blink::LocalFrameView::RunAccessibilitySteps
blink::LocalFrameView::RunPostLifecycleSteps
cc::ProxyMain::BeginMainFrame
The faulting trap has exactly one predecessor and the register feeding it is the switch (it->Type()) selector, so this is the CHECK that fires and not one of the other three fatal sites in the function. The stack is identical across all 9 dumps on one runtime build. Nothing is logged at the failure: the CHECK compiles to IMMEDIATE_CRASH() with no call to a check-failure handler, so --enable-logging --v=1 across five deaths produced zero Check failed lines. There is nothing to capture.
The failure has survived six app versions (1.1.8 → 1.1.13) and four runtime builds (.78 → .101). Each build repeats its own crash offset exactly.
Why accessibility is on at all
No assistive technology is running on this machine (no Narrator/NVDA/JAWS). Accessibility is on because the app turns it on itself: github.exe embeds, in its Tauri configuration, "additionalBrowserArgs": "--disable-features=… --force-renderer-accessibility". That switch is unconditional, is byte-identical in 1.1.13, and selects kAXModeComplete — which includes kInlineTextBoxes, the mode bit the failing path requires. It appears on the WebView2 browser process command line, not the renderer's.
Ruled out
Elapsed time, memory pressure, GPU/compositing, and back/forward cache are each excluded by measurement — details in the gist.
Activity-dependent. Across a full weekend of continuous uptime, zero deaths in 20 working-hours against 7.1 expected (P = 0.0008). All confirmed deaths fall between 08:00 and 17:59 local, so a renderer that is running but not being driven does not hit this check.
Workaround
Disabling renderer accessibility for this app stops it: 19.6 working-hours with zero crashes, against a baseline of one per 3.9 (P = 0.007). One launch that accidentally bypassed it crashed within 1.35 hours with the original signature. Copy-pasteable instructions: #3200 (comment)
It disables the accessibility tree outright, so it is a stopgap, and unusable for anyone relying on assistive technology.
Flags that do not fix it
--force-renderer-accessibility=basic/=form-controls— environment-variable arguments land before the app's own, and Chromium takes the last occurrence of a switch, so the app's bare--force-renderer-accessibilityoverrides them.--disable-renderer-accessibilityis a different switch and wins in either order.--disable-features=AccessibilityBlockFlowIterator— relocates the crash rather than removing it. It removes the guarded path but not the nullLayoutObject, so the work reroutes to the siblingAXInlineTextBox::NeighboringOnLine, which has noCHECK: the renderer still dies, now as a0xc0000005null dereference instead of a labelled abort. Call counts into the two leaves under load: stock 1480/2, with the flag 2/1213. Over 4.3 working-hours the crash rate was not distinguishable from baseline (2 deaths, p = 0.30), so this is not a claim that it crashes more often. 1.1.13 ships this flag.
What would help
The CHECK itself is a Blink bug and no public Chromium issue appears to exist for it. Two things are in the app's hands:
- Reconsider hard-coding
--force-renderer-accessibility. It is what puts this machine on the failing path with no assistive technology running. Enabling accessibility on demand would avoid the crash entirely for users who need no accessibility tree, without taking it from those who do. - Recover the view when
RenderProcessGonefires. The app logs nothing at the failure and can leave the window blank for up to 29m44s, while WebView2's ownBreadcrumbsrecords the event.
Minidumps for 24 captured deaths are retained and available on request.
Environment
- Copilot desktop app
github.exe1.1.8 – 1.1.13; Copilot CLI 1.0.79 – 1.0.80 - WebView2 runtime 151.0.4129.78 → .86 → .93 → .101 (deaths observed on all four) → .107 (in use only since the workaround, so no data; it still ships
ax_block_flow_iterator.cc) - Windows 11 build 26310, 63.6 GB RAM
Activity
bghgary commentedon Aug 26, 2026
[Commented by Copilot on behalf of @bghgary]
Workaround
Disables renderer accessibility for this app only. Measured here: 19.6 working-hours with zero crashes, against roughly one per 3.9 before.
Run once, elevated — writing under
HKCU\…\Policiesneeds admin:Quit the app completely, start it again, then confirm it took effect — this prints
True:To undo:
Do not use this if you rely on a screen reader or other assistive technology — it turns the accessibility tree off. The value name scopes it to
github.exe; never use*, which applies it to every WebView2 app on the machine. Verified on app 1.1.13 with WebView2 151.0.4129.107; it survives app updates.gabog commentedon Sep 1, 2026
Reporting that the registry
AdditionalBrowserArgumentsworkaround in this issue does not take effect on WebView2 152.Environment:
I applied the exact HKCU key from the workaround comment (value name
github.exe), fully quit the app including the tray icon, confirmed the key was written, then relaunched. The app's own logs confirm this was a clean quit and restart with the key already in place: the prior instance stopped logging at 16:36:21, the registry value was written at 16:36:40, and the new instance started at 16:36:49.After that clean restart, the WebView2 browser process still launches with
--force-renderer-accessibility, and the policy's--disable-renderer-accessibilitydoes not appear on the command line at all:I verified the registry value is correctly formed per Microsoft's documented format: named value
github.exe, type REG_SZ, in the current user's hive (SID matches the app's process owner), and the name matches the exact--webview-exe-name=github.exethe runtime reports. There is no HKLM override and no competing policy. So the policy is simply not being applied by WebView2 152.This workaround was verified in this issue on 151.0.4129.107, so 152 appears to have changed or regressed
AdditionalBrowserArgumentshandling. Net effect: on WebView2 152 there is currently no working mitigation via the registry policy.The crashes continue on 152: several renderer crashes today, all access violations (0xC0000005) at
msedge.dll +0xEF9F3C1, matching the null-dereference form described here (1.1.13+ shipping--disable-features=AccessibilityBlockFlowIterator, which relocates the CHECK into a null deref).gabog commentedon Sep 2, 2026
Follow-up: the environment-variable override (
WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS) also fails on WebView2 152, same as the registry policy.I set the user-level environment variable
WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--disable-renderer-accessibility, fully quit the app (including the tray icon), and relaunched.Proof it reached the app: I read the running github.exe process's actual environment block from memory, and the variable is present:
Yet the WebView2 browser process still launches with
--force-renderer-accessibilityand without--disable-renderer-accessibilityanywhere on its command line:Per the WebView2 documentation, when
additionalBrowserArgumentsis specified via the environment variable or the registry, "it is appended to the corresponding values inCreateCoreWebView2EnvironmentWithOptionsparameters." On 152 that append is not happening: the argument appears in neither the environment-variable path nor the registry path.So on WebView2 152.0.4191.53, both documented
AdditionalBrowserArgumentsoverride mechanisms are ignored, and there is currently no working user-side mitigation for this crash. The registry workaround in this issue was verified on 151.0.4129.107, so the override handling appears to have regressed between 151 and 152.Environment: app github.exe 1.1.14.0, WebView2 152.0.4191.53, Windows 11 build 26200.
bghgary commentedon Sep 2, 2026
[Responded by Copilot on behalf of @bghgary]
We see a different result with app 1.1.14 and WebView2 152.0.4191.53 on Windows build 26310. The per-executable registry policy is applied, and the WebView2 browser command line includes
--disable-renderer-accessibilitybefore the app’s--force-renderer-accessibility.No user-level
WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTSvariable is set. The differing Windows builds (26200 versus 26310) are one known environmental difference, but the cause of the discrepancy is not established.Aysamu commentedon Sep 2, 2026
Third machine on this crash, on Windows build 26200 — the same build as @gabog and not @bghgary's 26310. Adding a data point to the override discrepancy, plus the symbolized identity of the
+0xEF9F3C1offset and one further blocker on managed devices.Environment
github.exe1.1.14+0xEF9F3C1symbolized: it is the predicted sibling leaf@gabog reported crashes at
msedge.dll +0xEF9F3C1on this same runtime build and inferred they were the relocated null-dereference form. I see the identical offset, and the inference can be confirmed directly rather than inferred. Symbolized against the matching public PDB (msedge.dll.pdb, key23ABB196123C24124C4C44205044422E1, from msdl):That is exactly the sibling leaf this issue predicted the work would reroute into once
AccessibilityBlockFlowIteratoris disabled — named in the issue body asAXInlineTextBox::NeighboringOnLine, "which has noCHECK".From the minidump:
A null read with the operand register at zero is consistent with the same null
LayoutObjectthat trips theCHECKon the guarded path; here the pointer is dereferenced instead of asserted on.Three independently captured dumps on this machine give a byte-identical faulting offset, so this is deterministic rather than memory corruption. Roughly 15 renderer deaths over 43 hours of app uptime, activity-correlated as described in the issue body. WebView2's
BreadcrumbsrecordsTab1 RenderProcessGone; the app itself logs nothing.Incidentally, the crashed renderer's module list contains no graphics modules at all (22 modules loaded), which independently rules out GPU/compositing here.
On the 26200 vs 26310 override discrepancy
I cannot test the registry policy the way @gabog did, but the result points the same way and adds a second constraint.
On this corporate-managed install,
HKCU\SOFTWARE\Policiesis ACL-locked and a non-admin user cannot create subkeys under it at all:The workaround comment notes it "needs admin", but on a policy-managed device elevation is not available to the user either, so for that population it is a hard block rather than an inconvenience — independent of whether 152 would have honoured the key.
The environment-variable route is available to me but not usable:
WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTSat user scope also reaches Teams, Outlook and the AAD authentication broker, which are WebView2 hosts on this machine. And per @gabog's follow-up it does not take effect on 152 in any case.So the tally on build 26200 is now two machines where no documented override path is usable, against one machine on 26310 where the registry policy works. If it helps narrow the environmental difference: this machine is a Hyper-V VM, domain-joined and policy-managed.
No app-side opt-out exists in 1.1.14
Scanning the shipped
github.exe1.1.14 binary:force-renderer-accessibilityAccessibilityBlockFlowIteratordisable-renderer-accessibility1.1.14 still hard-codes the forcing switch, still ships the relocating flag, and exposes no setting or pass-through that would let a user turn the accessibility tree off for this app. Combined with the above, there is currently no user-accessible mitigation on a managed device on build 26200.
For anyone blocked meanwhile
The Copilot CLI (
copilot.exe) is not a WebView2 host, so it cannot reach this code path at all. That is a structural property rather than a lower crash rate, and it works as a fallback while this is open.Reinforcing "what would help" item 1
This machine has no assistive technology running and no need for an accessibility tree, yet it is placed on the failing path unconditionally. An opt-out — even an undocumented setting, or simply honouring
--disable-renderer-accessibilityas a pass-through from the app's own configuration — would resolve this for affected users without taking accessibility from anyone who needs it. Unlike the registry policy, an app-side switch would not depend onAdditionalBrowserArgumentsbehaving consistently across runtime and OS builds, which is now demonstrably not the case.Minidumps for the three captured deaths are retained and available on request.
FBakkensen commentedon Sep 3, 2026
Fourth machine, same
0xEF9F3C1offset on 152.0.4191.53 — and one new symptom: after the renderer dies, the hostgithub.exeitself stops responding, so the app cannot be closed from the tray and must be force-killed.Environment
github.exe1.1.14 (commit0d498e8)Two occurrences on 2026-09-02, identical signature
From
C:\ProgramData\Microsoft\Windows\WER\ReportArchive:Same offset @Aysamu symbolized to
blink::AXInlineTextBox::NeighboringOnLine + 0xF3. Before the runtime moved to 152 this machine had five renderer crashes in August on 151.0.4129.78/.86/.101 (offsets 82219836 / 82310033 / 82342107 — one offset per build, repeated exactly), matching the "each build repeats its own offset" observation in the issue body.New: the host process hangs too
Both times, the window did not stay at "blank until refreshed" — it stayed blank, and the app stopped responding altogether. Tray → Quit did nothing; only killing
github.exeworked. Windows recorded it:The app's own log (
%USERPROFILE%\.copilot\logs\github-app.<pid>.log) shows the sequence. The frontend WebSocket drops two seconds before the WER renderer report, the backend keeps running normally for 50 minutes (polling, diff builds, liveness probes all logged), and the next frontend-related line is when I activated the window — after which nothing more is logged until the kill:Second occurrence,
pid 101368: WS closed18:20:40Z, WER renderer at 20:20:42 local,Critical_github.exeat 20:23:54 — same shape.Two things stand out. The app logs nothing when the renderer dies — no
ProcessFailedhandling appears in the log, consistent with @Aysamu's "the app itself logs nothing". And the last thing logged before the hang iswebview_a11yannouncingEVENT_OBJECT_FOCUSon the web-content HWND on activation; with the renderer gone, that call — or whatever follows it on the UI thread — never returns. So on this machine the failure is not only a blank surface: activating the window after the crash wedges the host's message loop.Workaround status here
Same situation as @Aysamu: non-admin on a managed device,
HKCU\SOFTWARE\Policiesnot writable, andWEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTSat user scope would also reach Teams/Outlook/the auth broker. No usable mitigation.Side observation
github-app.110308.logalso contains 7,338 lines ofone per second for ~90 minutes after a browser-preview canvas was closed. Not related to the crash, but it is a retry loop with no backoff and probably wants its own issue.
WER folders and the two app logs are retained and available on request.
FBakkensen commentedon Sep 3, 2026
Third occurrence on my machine (previous two reported above, 2026-09-02 13:34 & 20:20 CEST).
2026-09-03 12:03:11 CEST — identical WER signature:
App version 1.1.14 (copilot-desktop-gh-2.96.0), Windows 11 build 26200.
New data points vs. my earlier reports:
github.exeprocess stayed responsive (no Event 1002 hang) — only the WebView2 surface went permanently white. So the host-hang I reported earlier is a secondary symptom, not constant.webview_a11y: announced EVENT_OBJECT_FOCUS on web-content HWND after activation— consistent with the--force-renderer-accessibilitytrigger theory in this thread.EBWebView\Crashpad\reports\75af31f9-eb09-49bf-a254-105c74ecc4f6.dmp, 8.2 MB) — happy to share with a maintainer through a private channel.gabog commentedon Sep 5, 2026
Update: after the app auto-updated to 1.1.15, the per-executable registry policy now takes effect on my machine, and the change tracks the WebView2 runtime version rather than the Windows build.
Same machine as my earlier reports, same Windows build (26200.9168), and the registry key is unchanged. The only things that changed are the app version and the bundled WebView2 runtime:
--force-renderer-accessibility.This speaks to the discrepancy raised earlier (my build 26200 not injecting the policy, while build 26310 did). On my machine the injection started working when the WebView2 runtime went from 152.0.4191.53 to 152.0.4191.66, with no change to the Windows build and no change to the registry key. So the deciding factor for whether the policy is injected looks like the WebView2 runtime version, not the OS build. Your machine was already on 26310 where injection worked on .53, so .53 injection may be environment-sensitive, while .66 injects on 26200 as well.
I have not yet confirmed the crash actually stops on .66. The app has only been running a short time. I will follow up with crash counts after a longer run.
Two related notes:
--force-renderer-accessibilityon 1.1.15, so the root-cause forcing is unchanged; this is a workaround being applied, not the force being removed.Environment: app 1.1.15, WebView2 152.0.4191.66, Windows 11 build 26200.9168.
gabog commentedon Sep 10, 2026
Follow-up after ~5 days on the workaround, now through app updates to 1.1.16 and 1.1.17.
The per-executable registry workaround has held on Windows build 26200.9168:
State after updating to 1.1.17:
--disable-renderer-accessibility(from the policy) followed by--force-renderer-accessibility(from the app). The disable flag continues to win, matching the earlier measurement.--force-renderer-accessibilityon 1.1.17, so the root-cause forcing is unchanged; this remains a workaround, not a fix.Neither the 1.1.16 nor the 1.1.17 changelog describes removing the forced accessibility or fixing the accessibility-tree serializer CHECK. 1.1.17 does list "Fixed crashes in the browser preview and code editor caused by rare timing issues during window teardown and text restoration," which may or may not be the same code path; I cannot confirm either way from here, and it does not remove the forcing.
Consistent with that, #3174 still has a report (2026-09-09) of the crash reproducing on 1.1.16 roughly every 3 to 5 minutes on a machine without the workaround. So the two states line up: forcing on plus no workaround still crashes; forcing on plus the disable workaround does not.
This reinforces that the durable fix is to stop hard-coding
--force-renderer-accessibility(or gate it on assistive technology actually being present), rather than relying on every affected user to apply the registry policy.Environment: app 1.1.17, WebView2 152.0.4191.66, Windows 11 build 26200.9168.
gabog commentedon Sep 15, 2026
Update: on app 1.1.20 the app no longer passes
--force-renderer-accessibility, and the crash has stopped here.Current state on this machine:
The WebView2 browser command line now contains neither accessibility flag:
This is an app-side change, not a runtime failure to inject arguments. The app's own
--disable-featureslist is still being applied, and it includesAccessibilityBlockFlowIterator, which is NOT part of the registry policy value I have set. So the app is still supplying its browser arguments successfully;--force-renderer-accessibilityis simply no longer among them.I cannot pin down which release dropped it. I sampled flags on 1.1.17 (present) and on 1.1.20 (absent), and did not sample 1.1.18 or 1.1.19, so it landed somewhere in that range. None of the 1.1.18, 1.1.19, 1.1.20, or 1.1.21 changelogs mention it.
Crash results since then: no renderer crash since 2026-09-10 22:54, which is roughly when WebView2 153 arrived. Crashpad has written no dumps and its metadata has not updated since that time, and there are no Windows AppHang or AppCrash events for
github.exein the last 10 days apart from one unrelated stack overflow (0xc00000fd) in the main process on 2026-09-10. Before this, I was seeing the blank-screen crash in clusters, at times every few minutes.One caveat that matters for anyone still relying on the workaround: the per-executable registry policy is NOT being injected on WebView2 153.0.4234.32. My key is still set, and
--disable-renderer-accessibilitydoes not appear on the command line. That is the same behavior I reported for 152.0.4191.53, and the opposite of 152.0.4191.66, where it was injected. So on 153 the registry workaround provides no protection. It does not matter while the app is not forcing accessibility, but it does mean the workaround is not a safety net on 153 if the forcing is ever reintroduced.Summary: the trigger appears to be gone on the app side, and this machine has been clean for about 4.5 days. It would be worth confirming whether removing
--force-renderer-accessibilitywas intentional, since it is not in any changelog, and whether the underlying accessibility-tree serializer crash was also addressed upstream.bghgary commentedon Oct 13, 2026
[Commented by Copilot on behalf of @bghgary]
Closing as resolved for the app: it no longer forces renderer accessibility, removing the trigger identified here. The forcing flag remains absent in app 1.1.29. This does not establish that the underlying Blink defect is fixed.