Skip to content

fix(ui): add existence check for session in updateConfirmingWorktreeRemoval #136

@dnlopes

Description

@dnlopes

Summary

The updateConfirmingWorktreeRemoval method in model.go accesses m.sessionState.Sessions[session.Name] without checking if the key exists, unlike other handlers (handleKillSession, handleArchiveSession) which use getFreshSessionInfo().

Problem

Location: internal/ui/model.go:743

When a user initiates a "kill session" action on a session with a worktree:

  1. handleKillSession uses getFreshSessionInfo() to check if session exists and has worktree
  2. If yes, it opens a confirmation dialog asking "Remove worktree too?"
  3. User makes a choice → updateConfirmingWorktreeRemoval handles the response

The gap is in step 3. Between steps 1 and 3, time passes while the user reads and interacts with the dialog. During this time, another process or user could delete the session.

Current code:

sessionInfo := m.sessionState.Sessions[session.Name]
worktreePath := sessionInfo.WorktreePath
repoPath := sessionInfo.RepoPath

If the session was deleted:

  • sessionInfo becomes a zero-value domain.Session{}
  • worktreePath and repoPath become empty strings
  • The code continues silently, potentially calling RemoveWorktree("", "") with unexpected behavior

Contrast with handleKillSession (line 580):

if sessionInfo, ok := m.getFreshSessionInfo(sessionName); ok && sessionInfo.WorktreePath != "" {
    // Safe: we know session exists
}

Why It Matters

  • Silent failures are hard to debug
  • Operating on stale/missing data can lead to confusing error messages
  • Inconsistent patterns make code harder to maintain

Proposed Solution

Add existence check before accessing session info:

sessionInfo, ok := m.sessionState.Sessions[session.Name]
if !ok {
    logging.Logger.Warn("Session no longer exists during worktree removal", "session", session.Name)
    m.state = stateList
    m.worktreeRemovalForm = nil
    m.sessionToKill = nil
    m.formRemoveWorktree = nil
    return m, m.sessionList.Init()
}

Related Code

  • handleKillSession (line 580) - correctly uses getFreshSessionInfo
  • handleArchiveSession (line 596) - correctly uses getFreshSessionInfo
  • getFreshSessionInfo helper (line 564) - loads fresh state and checks existence

Labels

  • bug
  • good first issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions