Summary
BreadcrumbMessengerHub.PostJson writes the message into its replay cache before broadcasting and
wraps the broadcast in no try/catch. If one attached surface throws - which a disposed
WebView2Messenger does - every attachment later in enumeration order silently never receives the
message, yet the cache records it as delivered, so no re-delivery ever occurs and a later Attach
replays a state the surviving surfaces never saw.
Environment
- OS/version: Windows 11 Pro 10.0.26200
- Python version: n/a (C# / .NET Framework 4.8.1 WinForms VSTO add-in with Microsoft WebView2)
- Command/flags used: n/a - reached through the QuickFiler ItemViewer breadcrumb surfaces
- Data source or fixture: two or more attached breadcrumb surfaces where one has been disposed
Steps to Reproduce
- Attach two breadcrumb surfaces to a single
BreadcrumbMessengerHub - in production the inline
selector and the popup surface.
- Dispose one surface's
WebView2Messenger without calling the hub's Detach. The two are
independently ordered calls (QuickFiler/Viewers/BreadcrumbItemViewerLifecycleCoordinator.cs:277
and :288), so this ordering is reachable.
- Post a breadcrumb message through the hub.
- Observe which surfaces received it, and inspect the hub's replay cache.
Expected Behavior
Either every live attachment receives the message, or a failure to deliver is contained and the cache
does not claim delivery. The hub already demonstrates the correct pattern in Attach, which wraps
its replay in try/catch with an explicit rollback
(QuickFiler/Viewers/BreadcrumbMessengerHub.cs:82-93).
Actual Behavior
PostJson caches at :130, then enumerates attachments at :131-134 with no exception handling. The
disposed surface throws ObjectDisposedException from WebView2Messenger.PostJson
(QuickFiler/Viewers/WebView2Messenger.cs:61 via :130-136). The exception propagates out of the
hub to the caller, attachments later in enumeration order are starved, and _cachedStates is not
rolled back.
Logs / Screenshots
Impact / Severity
Rationale: recorded by research as Low-Medium. Raised to Medium here because the corrupted replay
cache makes the resulting stale-surface state persistent rather than transient - no subsequent post
repairs it - and the ordering that triggers it is a normal disposal sequence rather than an exotic
race.
Source
From: docs/features/potential/2026-08-08-breadcrumb-hub-postjson-caches-before-broadcast-starves-attachments.md
Summary
BreadcrumbMessengerHub.PostJsonwrites the message into its replay cache before broadcasting andwraps the broadcast in no
try/catch. If one attached surface throws - which a disposedWebView2Messengerdoes - every attachment later in enumeration order silently never receives themessage, yet the cache records it as delivered, so no re-delivery ever occurs and a later
Attachreplays a state the surviving surfaces never saw.
Environment
Steps to Reproduce
BreadcrumbMessengerHub- in production the inlineselector and the popup surface.
WebView2Messengerwithout calling the hub'sDetach. The two areindependently ordered calls (
QuickFiler/Viewers/BreadcrumbItemViewerLifecycleCoordinator.cs:277and
:288), so this ordering is reachable.Expected Behavior
Either every live attachment receives the message, or a failure to deliver is contained and the cache
does not claim delivery. The hub already demonstrates the correct pattern in
Attach, which wrapsits replay in
try/catchwith an explicit rollback(
QuickFiler/Viewers/BreadcrumbMessengerHub.cs:82-93).Actual Behavior
PostJsoncaches at:130, then enumerates attachments at:131-134with no exception handling. Thedisposed surface throws
ObjectDisposedExceptionfromWebView2Messenger.PostJson(
QuickFiler/Viewers/WebView2Messenger.cs:61via:130-136). The exception propagates out of thehub to the caller, attachments later in enumeration order are starved, and
_cachedStatesis notrolled back.
Logs / Screenshots
System.ObjectDisposedExceptionraised fromWebView2Messenger.PostJson.Impact / Severity
Rationale: recorded by research as Low-Medium. Raised to Medium here because the corrupted replay
cache makes the resulting stale-surface state persistent rather than transient - no subsequent post
repairs it - and the ordering that triggers it is a normal disposal sequence rather than an exotic
race.
Source
From: docs/features/potential/2026-08-08-breadcrumb-hub-postjson-caches-before-broadcast-starves-attachments.md