Skip to content

Reset the query cache when a pane boundary recovers - #15341

Draft
mtsgrd wants to merge 1 commit into
masterfrom
mattias/pane-boundary-query-reset
Draft

Reset the query cache when a pane boundary recovers#15341
mtsgrd wants to merge 1 commit into
masterfrom
mattias/pane-boundary-query-reset

Conversation

@mtsgrd

@mtsgrd mtsgrd commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #15339, which merged before Copilot's review could be acted on. Copilot was right, and this fixes it.

The bug

The pane error boundaries from #15339 could clear their own state but never reset the query cache. A useSuspenseQuery keeps throwing its cached error until reset() is called, so the children rendered straight back into the same throw.

Two things had to be wrong together, and both were:

before after
pane boundaries receive onReset ❌ never wired ✅ from useQueryErrorResetBoundary()
when the error is cleared during render, in getDerivedStateFromProps — too early for onReset to run at all in the commit phase, so onReset runs before children re-render

Net effect: a failed suspense query in the details pane was stuck permanently, and Retry could not help — exactly the "quiet dead pane" failure the resetKeys work was meant to prevent. Details.tsx has 4 useSuspenseQuery call sites, so this was reachable.

The fix

  • ErrorBoundary resets in componentDidUpdate rather than getDerivedStateFromProps. The extra render pass is the point: onReset must land before the children render again.
  • Both panes in WorkspacePage pass onReset={resetQueryErrors}.

Verification

ErrorBoundary.query.test.tsx drives a real QueryClient with a failing suspense query and covers both routes back — via a reset key, and via Retry.

Both tests fail if the onReset call is removed, so they guard the actual defect rather than the shape of the code:

× recovers on a reset key once the query would succeed
× recovers on Retry once the query would succeed

pnpm -F @gitbutler/lite check, component tests (27 passing), oxlint, knip — clean.

A suspense query keeps throwing its cached error until the query cache is
reset, so clearing the boundary's own state is not enough: the children
render straight back into the same throw. Neither pane boundary was handed
that reset, and the details pane cleared its error during render via
getDerivedStateFromProps, which is too early for onReset to run at all --
so a failed query left the pane stuck, with Retry unable to help.

Move the reset to the commit phase so onReset runs before the children
render again, and give both panes the reset from useQueryErrorResetBoundary.
The extra render pass this costs is the point, not an oversight.

ErrorBoundary.query.test.tsx covers both routes back, on a reset key and on
Retry; both fail without the onReset call.

Follows up #15339, raised there by Copilot.
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