@@ -245,7 +245,7 @@ export function TerminalView() {
245245 const lastCreateTimeRef = useRef < number > ( 0 ) ;
246246 const isCreatingRef = useRef < boolean > ( false ) ;
247247 const prevProjectPathRef = useRef < string | null > ( null ) ;
248- const isRestoringLayoutRef = useRef < boolean > ( false ) ;
248+ const restoringProjectPathRef = useRef < string | null > ( null ) ;
249249 const [ newSessionIds , setNewSessionIds ] = useState < Set < string > > ( new Set ( ) ) ;
250250 const [ serverSessionInfo , setServerSessionInfo ] = useState < { current : number ; max : number } | null > ( null ) ;
251251 const hasShownHighRamWarningRef = useRef < boolean > ( false ) ;
@@ -438,11 +438,14 @@ export function TerminalView() {
438438 const currentPath = currentProject ?. path || null ;
439439 const prevPath = prevProjectPathRef . current ;
440440
441- // Skip if no change or if we're restoring layout
442- if ( currentPath === prevPath || isRestoringLayoutRef . current ) {
441+ // Skip if no change
442+ if ( currentPath === prevPath ) {
443443 return ;
444444 }
445445
446+ // If we're restoring a different project, that restore will be stale - let it finish but ignore results
447+ // The path check in restoreLayout will handle this
448+
446449 // Save layout for previous project (if there was one and has terminals)
447450 if ( prevPath && terminalState . tabs . length > 0 ) {
448451 saveTerminalLayout ( prevPath ) ;
@@ -462,13 +465,20 @@ export function TerminalView() {
462465
463466 if ( savedLayout && savedLayout . tabs . length > 0 ) {
464467 // Restore the saved layout - try to reconnect to existing sessions
465- isRestoringLayoutRef . current = true ;
468+ // Track which project we're restoring to detect stale restores
469+ restoringProjectPathRef . current = currentPath ;
466470
467471 // Clear existing terminals first (only client state, sessions stay on server)
468472 clearTerminalState ( ) ;
469473
470474 // Create terminals and build layout - try to reconnect or create new
471475 const restoreLayout = async ( ) => {
476+ // Check if we're still restoring the same project (user may have switched)
477+ if ( restoringProjectPathRef . current !== currentPath ) {
478+ console . log ( "[Terminal] Restore cancelled - project changed" ) ;
479+ return ;
480+ }
481+
472482 let failedSessions = 0 ;
473483 let totalSessions = 0 ;
474484 let reconnectedSessions = 0 ;
@@ -578,6 +588,12 @@ export function TerminalView() {
578588
579589 // For each saved tab, rebuild the layout
580590 for ( let tabIndex = 0 ; tabIndex < savedLayout . tabs . length ; tabIndex ++ ) {
591+ // Check if project changed during restore - bail out early
592+ if ( restoringProjectPathRef . current !== currentPath ) {
593+ console . log ( "[Terminal] Restore cancelled mid-loop - project changed" ) ;
594+ return ;
595+ }
596+
581597 const savedTab = savedLayout . tabs [ tabIndex ] ;
582598
583599 // Create the tab first
@@ -619,7 +635,10 @@ export function TerminalView() {
619635 duration : 5000 ,
620636 } ) ;
621637 } finally {
622- isRestoringLayoutRef . current = false ;
638+ // Only clear if we're still the active restore
639+ if ( restoringProjectPathRef . current === currentPath ) {
640+ restoringProjectPathRef . current = null ;
641+ }
623642 }
624643 } ;
625644
@@ -631,7 +650,8 @@ export function TerminalView() {
631650 // Also save when tabs become empty so closed terminals stay closed on refresh
632651 const saveLayoutTimeoutRef = useRef < NodeJS . Timeout | null > ( null ) ;
633652 useEffect ( ( ) => {
634- if ( currentProject ?. path && ! isRestoringLayoutRef . current ) {
653+ // Don't save while restoring this project's layout
654+ if ( currentProject ?. path && restoringProjectPathRef . current !== currentProject . path ) {
635655 // Debounce saves to prevent excessive localStorage writes during rapid changes
636656 if ( saveLayoutTimeoutRef . current ) {
637657 clearTimeout ( saveLayoutTimeoutRef . current ) ;
0 commit comments