@@ -2137,10 +2137,17 @@ export function useWorkflowExecution() {
21372137 includeStartConsoleEntry : true ,
21382138 } )
21392139
2140+ // Save original running entries so we can restore them if reconnection is interrupted.
2141+ // This ensures the next mount can retry reconnection.
2142+ const originalEntries = runningEntries
2143+ . filter ( ( e ) => e . executionId === executionId )
2144+ . map ( ( e ) => ( { ...e } ) )
2145+
21402146 // Defer clearing old entries until the first reconnection event arrives.
21412147 // This keeps hydrated entries visible during the network round-trip,
21422148 // avoiding a flash of empty console.
21432149 let cleared = false
2150+ let reconnectionComplete = false
21442151 const clearOnce = ( ) => {
21452152 if ( ! cleared ) {
21462153 cleared = true
@@ -2169,12 +2176,14 @@ export function useWorkflowExecution() {
21692176 } ,
21702177 onExecutionCompleted : ( ) => {
21712178 clearOnce ( )
2179+ reconnectionComplete = true
21722180 setCurrentExecutionId ( reconnectWorkflowId , null )
21732181 setIsExecuting ( reconnectWorkflowId , false )
21742182 setActiveBlocks ( reconnectWorkflowId , new Set ( ) )
21752183 } ,
21762184 onExecutionError : ( data ) => {
21772185 clearOnce ( )
2186+ reconnectionComplete = true
21782187 setCurrentExecutionId ( reconnectWorkflowId , null )
21792188 setIsExecuting ( reconnectWorkflowId , false )
21802189 setActiveBlocks ( reconnectWorkflowId , new Set ( ) )
@@ -2187,6 +2196,7 @@ export function useWorkflowExecution() {
21872196 } ,
21882197 onExecutionCancelled : ( ) => {
21892198 clearOnce ( )
2199+ reconnectionComplete = true
21902200 setCurrentExecutionId ( reconnectWorkflowId , null )
21912201 setIsExecuting ( reconnectWorkflowId , false )
21922202 setActiveBlocks ( reconnectWorkflowId , new Set ( ) )
@@ -2198,9 +2208,10 @@ export function useWorkflowExecution() {
21982208 } ,
21992209 } )
22002210 . catch ( ( error ) => {
2211+ reconnectionComplete = true
22012212 logger . warn ( 'Execution reconnection failed' , { executionId, error } )
22022213 clearExecutionEntries ( executionId )
2203- for ( const entry of runningEntries . filter ( ( e ) => e . executionId === executionId ) ) {
2214+ for ( const entry of originalEntries ) {
22042215 addConsole ( {
22052216 workflowId : entry . workflowId ,
22062217 blockId : entry . blockId ,
@@ -2219,10 +2230,18 @@ export function useWorkflowExecution() {
22192230
22202231 return ( ) => {
22212232 executionStream . cancel ( reconnectWorkflowId )
2222- // Reset execution state so the SPA guard doesn't block the next reconnection
2223- // attempt when the user navigates back to this workflow.
2224- // The cancel above causes an AbortError which is swallowed by
2225- // isClientDisconnectError, so the .catch() block never fires.
2233+
2234+ // If reconnection was interrupted (clearOnce fired but no terminal event arrived),
2235+ // restore the original running entries so the next mount can retry.
2236+ // cancel() causes an AbortError which is swallowed by isClientDisconnectError,
2237+ // so the .catch() block never fires — we must handle cleanup here.
2238+ if ( cleared && ! reconnectionComplete ) {
2239+ clearExecutionEntries ( executionId )
2240+ for ( const entry of originalEntries ) {
2241+ addConsole ( entry )
2242+ }
2243+ }
2244+
22262245 setCurrentExecutionId ( reconnectWorkflowId , null )
22272246 setIsExecuting ( reconnectWorkflowId , false )
22282247 setActiveBlocks ( reconnectWorkflowId , new Set ( ) )
0 commit comments