Skip to content

Main-window WebView2 renderer self-aborts with STATUS_BREAKPOINT (0x80000003): root cause and verified workaround #3200

Description

@bghgary

[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-accessibility overrides them. --disable-renderer-accessibility is a different switch and wins in either order.
  • --disable-features=AccessibilityBlockFlowIteratorrelocates the crash rather than removing it. It removes the guarded path but not the null LayoutObject, so the work reroutes to the sibling AXInlineTextBox::NeighboringOnLine, which has no CHECK: the renderer still dies, now as a 0xc0000005 null 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:

  1. 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.
  2. Recover the view when RenderProcessGone fires. The app logs nothing at the failure and can leave the window blank for up to 29m44s, while WebView2's own Breadcrumbs records the event.

Minidumps for 24 captured deaths are retained and available on request.

Environment

  • Copilot desktop app github.exe 1.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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions