From 42adc873377e8da782558be0ddb0071975bf8a76 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Mon, 6 Apr 2026 19:15:37 -0700 Subject: [PATCH 1/2] fix(sockets): joining currently deleted workflow --- .../workspace/providers/socket-provider.tsx | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/workspace/providers/socket-provider.tsx b/apps/sim/app/workspace/providers/socket-provider.tsx index b2257280c10..21c7610b74c 100644 --- a/apps/sim/app/workspace/providers/socket-provider.tsx +++ b/apps/sim/app/workspace/providers/socket-provider.tsx @@ -166,6 +166,7 @@ export function SocketProvider({ children, user }: SocketProviderProps) { const positionUpdateTimeouts = useRef>(new Map()) const isRejoiningRef = useRef(false) const pendingPositionUpdates = useRef>(new Map()) + const deletedWorkflowIdRef = useRef(null) const generateSocketToken = async (): Promise => { const res = await fetch('/api/auth/socket-token', { @@ -373,6 +374,7 @@ export function SocketProvider({ children, user }: SocketProviderProps) { logger.warn(`Workflow ${data.workflowId} has been deleted`) setCurrentWorkflowId((current) => { if (current === data.workflowId) { + deletedWorkflowIdRef.current = data.workflowId setPresenceUsers([]) return null } @@ -500,7 +502,11 @@ export function SocketProvider({ children, user }: SocketProviderProps) { if (error?.type === 'SESSION_ERROR') { const workflowId = urlWorkflowIdRef.current - if (workflowId && !isRejoiningRef.current) { + if ( + workflowId && + !isRejoiningRef.current && + deletedWorkflowIdRef.current !== workflowId + ) { isRejoiningRef.current = true logger.info(`Session expired, rejoining workflow: ${workflowId}`) socketInstance.emit('join-workflow', { @@ -552,13 +558,25 @@ export function SocketProvider({ children, user }: SocketProviderProps) { const hydrationPhase = useWorkflowRegistryStore((s) => s.hydration.phase) useEffect(() => { - if (!socket || !isConnected || !urlWorkflowId) return + if (!socket || !isConnected || !urlWorkflowId) { + if (!urlWorkflowId) { + deletedWorkflowIdRef.current = null + } + return + } if (hydrationPhase === 'creating') return // Skip if already in the correct room if (currentWorkflowId === urlWorkflowId) return + // Prevent rejoining a workflow that was just deleted. The URL param may + // still reference the old workflow while router.push() propagates. + if (deletedWorkflowIdRef.current === urlWorkflowId) { + return + } + deletedWorkflowIdRef.current = null + logger.info( `URL workflow changed from ${currentWorkflowId} to ${urlWorkflowId}, switching rooms` ) From d31bd1b3dc5240214efc9068757811cd0386dc8d Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Mon, 6 Apr 2026 19:28:25 -0700 Subject: [PATCH 2/2] address comments --- apps/sim/app/workspace/providers/socket-provider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sim/app/workspace/providers/socket-provider.tsx b/apps/sim/app/workspace/providers/socket-provider.tsx index 21c7610b74c..d04cc6e0fe2 100644 --- a/apps/sim/app/workspace/providers/socket-provider.tsx +++ b/apps/sim/app/workspace/providers/socket-provider.tsx @@ -372,9 +372,9 @@ export function SocketProvider({ children, user }: SocketProviderProps) { socketInstance.on('workflow-deleted', (data) => { logger.warn(`Workflow ${data.workflowId} has been deleted`) + deletedWorkflowIdRef.current = data.workflowId setCurrentWorkflowId((current) => { if (current === data.workflowId) { - deletedWorkflowIdRef.current = data.workflowId setPresenceUsers([]) return null }