Repository navigation
Composer load no longer surfaces a transient owner miss as a raw error - #1177
Conversation
…shows the raw banner Navigating home popped "Loading the composer: No response received in hub cache/… for request SubscribeRequest → target rbuergi/_Thread/ThreadComposer" in the error modal. The composer grain had idle-collected and its reactivation outran the 60 s request budget — the exact failure class MeshNodeStreamCache.IsTransientOwnerFailure documents as "forwarded to the current subscriber, whose CALLER retries". Every layout area implements that contract via RetryAreaWithBackoff(ShouldRetryArea); the two composer-node readers never did: - ThreadChatView.OpenComposerProjection surfaced the first failure verbatim (SurfaceError → portal error modal). It now retries with the same bounded backoff, and a transient failure that survives the whole budget is logged at Warning and stays silent — the next chat rebind resubscribes naturally. Only non-transient failures still surface. - ThreadSidePanelContent.OpenComposerObserver died silently on the first miss (Debug log), leaving Send-click navigation inert for the circuit's lifetime. Same bounded retry; the give-up log is promoted Debug → Warning permanently because a dead navigation observer is a real defect worth seeing in Loki, and it only fires after the retry budget is exhausted (negligible volume). The transient classification itself is already pinned by AreaErrorClassifierTest (the "No response received in hub … SubscribeRequest" banner) and AreaStreamRetryTest; this change is the missing wiring around those tested helpers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes a transient UX regression in the Blazor Portal chat composer: when the per-user composer hub/grain has been idle-collected and reactivation exceeds the request budget, the portal no longer surfaces the raw “No response received in hub … target hub was not found” error to users, and the side-panel observer no longer dies silently on the first miss.
Changes:
- Wire both composer readers (
ThreadChatViewprojection + side-panel observer) through the existing bounded retry helper (RetryAreaWithBackoff(AreaErrorClassifier.ShouldRetryArea)). - Keep non-transient failures surfaced in the main chat view, while transient failures that outlive the retry budget are logged and remain silent (matching the intended stream-cache contract).
- Add a WhatsNew entry documenting the user-visible behavior change.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/MeshWeaver.Blazor.Portal/Chat/ThreadSidePanelContent.razor.cs | Adds bounded retry to the composer observer and upgrades the “give up” log to Warning to avoid silently inert navigation after a transient miss. |
| src/MeshWeaver.Blazor.Portal/Chat/ThreadChatView.razor.cs | Adds bounded retry to the composer projection and suppresses end-user surfacing for exhausted transient failures while still surfacing non-transient errors. |
| src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-10-the-chat-input-no-longer-greets-you-with-a-technical-error.md | Documents the fix and the improved behavior for users. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
This PR resolves the actionable defect in issue #1175 (auto-filed tonight from the same banner on |
Symptom
Navigating to the home page on memex.meshweaver.cloud popped a raw framework error in the portal modal:
Nothing was actually broken — dismissing it and carrying on worked.
Root cause
The per-user composer grain had idle-collected, and its reactivation outran the 60 s request budget. That is the exact failure class
MeshNodeStreamCache.IsTransientOwnerFailuredocuments: the error is forwarded to the current subscriber for the caller to retry, and the cache stays clean so a resubscribe re-probes. Every layout area implements that contract viaRetryAreaWithBackoff(AreaErrorClassifier.ShouldRetryArea)— but the two composer-node readers never did:ThreadChatView.OpenComposerProjectionsurfaced the very first failure verbatim (SurfaceError→ portal error modal).ThreadSidePanelContent.OpenComposerObserverdied silently on the first miss (Debug log), leaving Send-click navigation inert for the circuit's whole lifetime.Fix
Both readers now use the same bounded, backoff-throttled retry as every layout area. A transient failure that survives the whole retry budget is logged at Warning and stays silent (the raw banner is hostile and unactionable; the next rebind resubscribes naturally). Non-transient failures still surface. The side panel's give-up log is promoted Debug → Warning permanently — a dead navigation observer is a real defect worth seeing, and it only fires after the retry budget is exhausted.
No new classification or retry logic: the transient predicate is already pinned by
AreaErrorClassifierTest(including the "No response received in hub … SubscribeRequest" banner) and the backoff byAreaStreamRetryTest. This PR is the missing wiring around those tested helpers, so there is no unbounded-resubscribe storm risk (the 2026-06-14 wedge class).Verification
dotnet build src/MeshWeaver.Blazor.Portal -c Release -warnaserror— clean, 0 warnings.WhatsNewEntryIntegrityTest— passed (entry2026-08-10-the-chat-input-no-longer-greets-you-with-a-technical-error.md, Category: Fix).🤖 Generated with Claude Code