Skip to content

Composer load no longer surfaces a transient owner miss as a raw error - #1177

Merged
rbuergi merged 1 commit into
mainfrom
fix/composer-transient-subscribe
Aug 10, 2026
Merged

rbuergi merged 1 commit into
mainfrom
fix/composer-transient-subscribe

Conversation

@rbuergi

@rbuergi rbuergi commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Symptom

Navigating to the home page on memex.meshweaver.cloud popped a raw framework error in the portal modal:

Loading the composer: No response received in hub cache/gmIIqhF220CKKxqxgY_J7Q within 00:01:00 for request SubscribeRequest (id=…) → target rbuergi/_Thread/ThreadComposer. The request may have been undeliverable or the target hub was not found.

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.IsTransientOwnerFailure documents: 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 via RetryAreaWithBackoff(AreaErrorClassifier.ShouldRetryArea) — but the two composer-node readers never did:

  • ThreadChatView.OpenComposerProjection surfaced the very first failure verbatim (SurfaceError → portal error modal).
  • ThreadSidePanelContent.OpenComposerObserver died 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 by AreaStreamRetryTest. 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 (entry 2026-08-10-the-chat-input-no-longer-greets-you-with-a-technical-error.md, Category: Fix).

🤖 Generated with Claude Code

…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>
Copilot AI lite review requested due to automatic review settings August 10, 2026 20:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 (ThreadChatView projection + 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.

@rbuergi

rbuergi commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

This PR resolves the actionable defect in issue #1175 (auto-filed tonight from the same banner on rsalzmann/_Thread/ThreadComposer, pod …6bd9c46f8b-z9t6r, 14:13–14:20Z). Evidence-based triage on the issue: #1175 (comment) — consider adding Fixes #1175 to the body so the merge closes it (the server-side starvation that made the owner probe slow in that window is tracked separately in #1172).

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

705 tests  ±0   705 ✅ ±0   13m 47s ⏱️ +8s
 10 suites ±0     0 💤 ±0 
 10 files   ±0     0 ❌ ±0 

Results for commit 9d9c826. ± Comparison against base commit b4920dc.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

1 194 tests  ±0   1 194 ✅ ±0   6m 28s ⏱️ +4s
   11 suites ±0       0 💤 ±0 
   11 files   ±0       0 ❌ ±0 

Results for commit 9d9c826. ± Comparison against base commit b4920dc.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

2 021 tests  ±0   2 019 ✅ ±0   6m 55s ⏱️ +2s
   11 suites ±0       2 💤 ±0 
   11 files   ±0       0 ❌ ±0 

Results for commit 9d9c826. ± Comparison against base commit b4920dc.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

1 786 tests  ±0   1 594 ✅ ±0   7m 41s ⏱️ -44s
   11 suites ±0     192 💤 ±0 
   11 files   ±0       0 ❌ ±0 

Results for commit 9d9c826. ± Comparison against base commit b4920dc.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

   11 files  ±0     11 suites  ±0   7m 50s ⏱️ - 1m 15s
1 984 tests ±0  1 876 ✅ ±0  108 💤 ±0  0 ❌ ±0 
2 168 runs  +1  2 060 ✅ +1  108 💤 ±0  0 ❌ ±0 

Results for commit 9d9c826. ± Comparison against base commit b4920dc.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

1 351 tests  ±0   1 346 ✅ ±0   9m 58s ⏱️ +29s
   11 suites ±0       5 💤 ±0 
   11 files   ±0       0 ❌ ±0 

Results for commit 9d9c826. ± Comparison against base commit b4920dc.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

   65 files  ±0     65 suites  ±0   52m 42s ⏱️ - 1m 16s
9 041 tests ±0  8 734 ✅ ±0  307 💤 ±0  0 ❌ ±0 
9 225 runs  +1  8 918 ✅ +1  307 💤 ±0  0 ❌ ±0 

Results for commit 9d9c826. ± Comparison against base commit b4920dc.

@rbuergi
rbuergi merged commit bd505ca into main Aug 10, 2026
19 checks passed
@rbuergi
rbuergi deleted the fix/composer-transient-subscribe branch August 19, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants