From 18b746d525d657f85138bf1ec1bcfd6215f3d09d Mon Sep 17 00:00:00 2001 From: Akash! Date: Thu, 16 Jul 2026 17:53:20 +0530 Subject: [PATCH] fix(metadata): invalidate metadata store on SSE reconnect (#22504) (#22562) ## Fixes Fixes #22504 ## Description This PR fixes a bug where metadata updates (like creating a new field or a page layout) were missed if an open tab was temporarily disconnected from the server (e.g., tab backgrounded or a network blip). Because the frontend's metadata store relies on live SSE deltas for freshness, any gap in the connection meant the new metadata would never reach the client unless a full reload occurred. This often resulted in "No Data" states for newly created layouts or widgets. **Changes:** - Updated `SSEClientEffect.tsx` to call `invalidateMetadataStore()` upon a successful SSE reconnection. - Re-syncing the metadata store on reconnect ensures that any events missed during the disconnected gap are retrieved durably without requiring a manual page refresh. ## Testing 1. Open a record page tab in a workspace. 2. From an app front component or DevTools, trigger a field creation via the metadata API (`createOneField` / `page-layout` mutations). 3. Briefly disconnect the network or restart the server so the SSE stream drops during the mutation. 4. Re-establish the connection. 5. The tab should automatically refetch the metadata and reflect the new field/layout without needing a manual reload, instead of getting stuck in a "No Data" state. Review in cubic --- .../src/modules/sse-db-event/components/SSEClientEffect.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/twenty-front/src/modules/sse-db-event/components/SSEClientEffect.tsx b/packages/twenty-front/src/modules/sse-db-event/components/SSEClientEffect.tsx index 85421c2f71..ee5dbfcfbb 100644 --- a/packages/twenty-front/src/modules/sse-db-event/components/SSEClientEffect.tsx +++ b/packages/twenty-front/src/modules/sse-db-event/components/SSEClientEffect.tsx @@ -1,6 +1,7 @@ import { useHasAccessTokenPair } from '@/auth/hooks/useHasAccessTokenPair'; import { tokenPairState } from '@/auth/states/tokenPairState'; import { dispatchBrowserEvent } from '@/browser-event/utils/dispatchBrowserEvent'; +import { useInvalidateMetadataStore } from '@/metadata-store/hooks/useInvalidateMetadataStore'; import { SSE_CLIENT_RECONNECTED_EVENT_NAME } from '@/sse-db-event/constants/SseClientReconnectedEventName'; import { useHandleSseClientConnectionRetry } from '@/sse-db-event/hooks/useHandleSseClientConnectionRetry'; import { activeQueryListenersState } from '@/sse-db-event/states/activeQueryListenersState'; @@ -19,6 +20,7 @@ export const SSEClientEffect = () => { const hasAccessTokenPair = useHasAccessTokenPair(); const [sseClient, setSseClient] = useAtomState(sseClientState); const tokenPair = useAtomStateValue(tokenPairState); + const { invalidateMetadataStore } = useInvalidateMetadataStore(); const handleSSEClientConnected = useCallback( (reconnected: boolean) => { @@ -31,10 +33,11 @@ export const SSEClientEffect = () => { } if (reconnected) { + invalidateMetadataStore(); dispatchBrowserEvent(SSE_CLIENT_RECONNECTED_EVENT_NAME); } }, - [store], + [store, invalidateMetadataStore], ); const { handleSseClientConnectionRetry } =