[BUG] /resume finds no conversations when submodule has an active secondary worktree
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
/resume returns "No conversations found to resume" in a git submodule that has an active secondary worktree (git worktree add), even though 90+ session .jsonl files exist on disk in the correct ~/.claude/projects/<key>/ directory.
Another submodule in the same parent repo — without a secondary worktree — can /resume fine with the same Claude Code version.
What Should Happen?
/resume should list all past sessions in the submodule regardless of whether secondary worktrees exist.
Error Messages/Logs
> /resume
No conversations found to resume
No error or stack trace — it silently returns empty results.
Steps to Reproduce
- Create a parent repo with two submodules:
``bash``
mkdir parent && cd parent && git init
git submodule add <repo-A-url> projects/repo-a
git submodule add <repo-B-url> projects/repo-b
cd projects/repo-aand run a few Claude Code sessions (sessions are saved normally).
- Create a secondary worktree inside repo-a:
``bash``
git worktree add ../repo-a--feature feature-branch
- Run
/resumeinprojects/repo-a→ "No conversations found to resume"
- Verify
projects/repo-b(no secondary worktree) →/resumeworks fine.
- Remove the worktree:
``bash``
git worktree remove repo-a--feature
- Run
/resumeinprojects/repo-aagain → sessions appear normally.
Root Cause Analysis
Note: The analysis below is based on decompiled/extracted TypeScript source from the Claude Code npm package (v2.1.96), not official published source. Line numbers and function names are approximate and may not match internal references exactly.
The issue is a path-mismatch chain across two functions:
1. getWorktreePaths() — submodule main worktree path is .git/modules/, not the checkout dir
git worktree list --porcelain inside a submodule reports the main worktree as the bare git directory:
worktree /path/to/parent/.git/modules/projects/repo-a ← NOT the actual checkout
worktree /path/to/parent/projects/repo-a--feature ← secondary worktree
Then currentWorktree matching fails because cwd (/path/to/parent/projects/repo-a) matches neither path:
const currentWorktree = worktreePaths.find(
path => cwd === path || cwd.startsWith(path + sep), // both checks fail
)
Result: currentWorktree = undefined, both paths go into otherWorktrees (length = 2).
2. getStatOnlyLogsForWorktrees() — the <= 1 guard is skipped, prefix matching fails
if (worktreePaths.length <= 1) {
// This fallback uses getOriginalCwd() directly → works correctly
// But with 2 worktree paths, this branch is SKIPPED
return getSessionFilesLite(getProjectDir(cwd), undefined, cwd)
}
The prefix matching loop then sanitizes both worktree paths and tries to match them against ~/.claude/projects/ directories:
| Sanitized prefix | Actual session dir key | Match? |
|---|---|---|
| -path-to-parent-.git-modules-projects-repo-a | -path-to-parent-projects-repo-a | ❌ |
| -path-to-parent-projects-repo-a--feature | -path-to-parent-projects-repo-a | ❌ |
Neither prefix matches → 0 sessions returned.
Why submodules without secondary worktrees work: only 1 worktree path → length <= 1 → fallback to getOriginalCwd() → correct path resolution.
Suggested Fix
In getWorktreePaths(), when cwd doesn't match any parsed worktree path (common for submodules), include cwd itself:
if (!currentWorktree) {
return [cwd, ...otherWorktrees]
}
Or in getStatOnlyLogsForWorktrees(), always include the current project dir in the scan regardless of worktree matching.
Is this a regression?
I don't know
Claude Code Version
2.1.96 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Related issues with similar symptoms but different root causes:
- #29256 (worktree + submodule)
- #24729 (sessions-index.json not generated)
This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗