Skip to content

fix(web): keep the signed-out message alive and unqueued - #2529

Merged
tyler-dane merged 3 commits into
mainfrom
claude/web-silent-write-failures
Aug 1, 2026
Merged

fix(web): keep the signed-out message alive and unqueued#2529
tyler-dane merged 3 commits into
mainfrom
claude/web-silent-write-failures

Conversation

@tyler-dane

Copy link
Copy Markdown
Contributor

Problem

Investigating a report of "my event disappeared and I got no indication of an error", two independent ways the one message telling a user their write failed could never reach them:

  1. A document navigation destroyed it. signOut() raises a toast and then calls window.location.assign("/week"). That is a full page load, so the toast is torn down before it can be read. The early return means this only happens when the user is not already on the calendar route — which is precisely the case where the message matters, since they are also being moved away from where they were.

  2. The toast could be silently queued out. ToastContainer had limit={1}, so any routine toast already on screen (an undo notice, an autosave confirmation) pushes a critical "you've been signed out" into a queue the user may never see.

Together: the user's write fails, their optimistic edit rolls back, and nothing explains why.

Changes

  • signOut routes in-app via the router singleton instead of assigning window.location. SessionExpiredToast already reaches the router this way, including the dynamic import that avoids the module cycle, so this follows an established path rather than inventing one.
  • limit={1}limit={3}.

Tests

The navigating branch of signOut had no coverage — the existing test pins the already-on-calendar case and notes it does so specifically to skip the jsdom-unsupported navigation. Adds a test for the branch that was actually broken.

24/24 api.util tests pass, 1519/1519 web tests pass (checked for mock.module leakage across files), type-check and lint clean.

Not included

The mutation layer still swallows 401 in handleError, deferring to this interceptor. That is now a safe assumption again since the interceptor's message survives, but it is worth revisiting alongside a MutationCache.onError backstop.

🤖 Generated with Claude Code

tyler-dane and others added 3 commits July 31, 2026 19:15
Two ways the one message telling a user their write failed could never reach
them:

- signOut raised a toast and then assigned window.location, and a document
  navigation tears the toast down. The early return meant this only happened
  on routes other than the calendar, which is exactly where the message was
  needed. Route in-app instead, the same way SessionExpiredToast already
  reaches the router.
- ToastContainer allowed one toast at a time, so any routine toast already on
  screen silently queued out a critical one behind it.

Adds coverage for the navigating branch, which had none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Its only caller was the sign-out path, which now routes in-app.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The limit raise broke calendar-experience keyboard selection consistently
across all 3 Playwright retries. Isolating it from the navigation fix, which
is the substantive change here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tyler-dane

Copy link
Copy Markdown
Contributor Author

Note: the ToastContainer limit raise (1 → 3) was reverted from this PR. It broke calendar-experience "supports keyboard selection" consistently across all 3 Playwright retries — additional simultaneous toasts appear to overlay or steal focus from the calendar combobox. e2e passed once isolated.

The underlying gap is real (a critical toast can still be silently queued behind a routine one), but it needs that interaction understood before it lands. Tracked as a follow-up.

@tyler-dane
tyler-dane merged commit a77a310 into main Aug 1, 2026
20 checks passed
@tyler-dane
tyler-dane deleted the claude/web-silent-write-failures branch August 1, 2026 01:33
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.

1 participant