Skip to content

fix(chat): suppress Unauthorized unhandled rejection from optimistic init#692

Merged
Movm merged 1 commit intomasterfrom
fix/chat-suppress-unauthorized-rejection
Apr 26, 2026
Merged

fix(chat): suppress Unauthorized unhandled rejection from optimistic init#692
Movm merged 1 commit intomasterfrom
fix/chat-suppress-unauthorized-rejection

Conversation

@Movm
Copy link
Copy Markdown
Collaborator

@Movm Movm commented Apr 26, 2026

Summary

Stale cached userId in localStorage triggers eager threadListAdapter.initialize() on /login before useAuth clears the session. The resulting 401 from POST /api/chat-service/threads surfaces as an unhandled rejection captured by Sentry — even though onUnauthorized() in chatConfig already handles the redirect side effect.

This extends the existing "Thread not found" suppression in GrueneratorChatProvider to also drop "Unauthorized" rejections — same root-cause class (assistant-ui optimisticUpdate paths we can't intercept via onClick).

Root cause

  1. Zustand authStore rehydrates synchronously from localStorage (15-min TTL cache).
  2. On /login, cached userId is non-empty even though the backend session is invalid.
  3. The if (!userId) return children guard at GrueneratorChatProvider.tsx:421 passes; runtime mounts.
  4. assistant-ui's optimisticUpdate.initialize eagerly calls threadListAdapter.initialize(), which POSTs /api/chat-service/threads.
  5. Backend returns 401, request() in ChatContext.tsx:33 calls onUnauthorized() then throw new Error('Unauthorized').
  6. The rejection is re-emitted asynchronously by assistant-ui's optimistic rollback, bypassing history.load's try/catch — Sentry captures it.

The redirect side effect already happens before the throw, so suppressing the unhandled rejection is purely about Sentry noise.

GlitchTip issue: GRUENERATOR-46 (494 events).

Test plan

  • Verify normal chat thread creation still works for authenticated users
  • Verify "Thread not found" suppression still works (delete a thread)
  • Verify a 401 on /login no longer hits Sentry but onUnauthorized redirect still fires when the user is on a protected page

…init

Stale cached userId in localStorage triggers eager threadListAdapter.initialize()
on /login before useAuth clears the session. The resulting 401 from POST
/api/chat-service/threads surfaces as an unhandled rejection captured by Sentry,
even though onUnauthorized() in chatConfig already fires the redirect.

Extends the existing "Thread not found" suppression in GrueneratorChatProvider
to also drop "Unauthorized" rejections — same root cause class (assistant-ui
optimisticUpdate paths we can't intercept via onClick).
@Movm Movm merged commit 6611124 into master Apr 26, 2026
10 of 11 checks passed
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