From 3349fb95ca5422d10fbd8064ece7a3c384b146be Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Fri, 17 Apr 2026 14:52:06 +1000 Subject: [PATCH] fix(layout): guard SortableWorkspace against undefined project during server swap bootstrapDirectory's setStore fires while a server swap is cascading; currentProject() can already be undefined by the time these memos re-run, which threw 'Cannot read properties of undefined (reading worktree)' from local/workspaceValue/WorkspaceActions root. Optional-chain the props.project reads so the component survives the transient undefined before the enclosing Show unmounts it. --- .../app/src/pages/layout/sidebar-workspace.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/app/src/pages/layout/sidebar-workspace.tsx b/packages/app/src/pages/layout/sidebar-workspace.tsx index e3b0ccd77c..b6685d35d7 100644 --- a/packages/app/src/pages/layout/sidebar-workspace.tsx +++ b/packages/app/src/pages/layout/sidebar-workspace.tsx @@ -319,12 +319,20 @@ export const SortableWorkspace = (props: { }) const slug = createMemo(() => base64Encode(props.directory)) const sessions = createMemo(() => sortedRootSessions(workspaceStore, props.sortNow())) - const local = createMemo(() => props.directory === props.project.worktree) + // Guard against `props.project` being transiently undefined during a + // server-switch cascade. The parent renders + // {(dir) => } + // where `project()` can flip to undefined while the enclosing + // gate hasn't yet unmounted this child. Bootstrap's setStore can then fire + // these memos with stale props. + const local = createMemo(() => props.directory === (props.project?.worktree ?? "")) const active = createMemo(() => workspaceKey(props.ctx.currentDir()) === workspaceKey(props.directory)) const workspaceValue = createMemo(() => { const branch = workspaceStore.vcs?.branch const name = branch ?? getFilename(props.directory) - return props.ctx.workspaceName(props.directory, props.project.id, branch) ?? name + const projectId = props.project?.id + if (!projectId) return name + return props.ctx.workspaceName(props.directory, projectId, branch) ?? name }) const open = createMemo(() => props.ctx.workspaceExpanded(props.directory, local())) const boot = createMemo(() => open() || active()) @@ -423,7 +431,7 @@ export const SortableWorkspace = (props: { openEditor={props.ctx.openEditor} showResetWorkspaceDialog={props.ctx.showResetWorkspaceDialog} showDeleteWorkspaceDialog={props.ctx.showDeleteWorkspaceDialog} - root={props.project.worktree} + root={props.project?.worktree ?? props.directory} clearHoverProjectSoon={props.ctx.clearHoverProjectSoon} navigateToNewSession={() => navigate(`/${slug()}/session`)} />