From 10b8f06463b05380aaa4d48d8acf8caaa1f7253f Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Tue, 2 Jun 2026 17:05:57 +1000 Subject: [PATCH] fix(serverless): clear React Query cache on workspace switch Channel lists, message timelines, members, and agent lists are keyed in React Query without the workspace id, so switching workspaces bled the previous workspace's channels/data into the new one. resetWorkspaceState() now calls queryClient.clear() alongside the existing module-singleton resets, per the AGENTS.md workspace-switch contract. --- desktop/src/features/workspaces/useWorkspaceInit.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/desktop/src/features/workspaces/useWorkspaceInit.ts b/desktop/src/features/workspaces/useWorkspaceInit.ts index 1f8ae1e80..48b2f1d72 100644 --- a/desktop/src/features/workspaces/useWorkspaceInit.ts +++ b/desktop/src/features/workspaces/useWorkspaceInit.ts @@ -1,4 +1,5 @@ import { useEffect, useRef, useState } from "react"; +import { type QueryClient, useQueryClient } from "@tanstack/react-query"; import { relayClient } from "@/shared/api/relayClient"; import { @@ -20,12 +21,17 @@ import type { Workspace } from "./types"; * cache or singleton that holds workspace data, add its reset here. * See AGENTS.md "Workspace Switching" for the full contract. */ -function resetWorkspaceState(): void { +function resetWorkspaceState(queryClient: QueryClient): void { relayClient.disconnect(); resetAgentObserverStore(); resetMediaCaches(); clearSearchHitEventCache(); clearAllDrafts(); + // Clear ALL React Query caches. Channel lists, message timelines, members, + // agents, etc. are keyed without the workspace id, so without this the + // previous workspace's data (e.g. its channels) bleeds into the new one on + // switch. The key-based remount of refetches everything fresh. + queryClient.clear(); } type WorkspaceInitResult = @@ -56,6 +62,8 @@ export function useWorkspaceInit( appliedKey: null, }); + const queryClient = useQueryClient(); + // Track whether this is the initial mount or a workspace switch. // On the initial mount we skip resetting singletons (they're fresh). const hasInitializedRef = useRef(false); @@ -111,7 +119,7 @@ export function useWorkspaceInit( // On workspace switch (not initial mount), reset module singletons // so the new tree starts with a clean slate. if (hasInitializedRef.current) { - resetWorkspaceState(); + resetWorkspaceState(queryClient); } hasInitializedRef.current = true;