claude-code - 💡(How to fix) Fix [BUG] /resume finds no conversations when submodule has an active secondary worktree [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#45179Fetched 2026-04-09 08:11:27
View on GitHub
Comments
2
Participants
2
Timeline
5
Reactions
0
Author
Timeline (top)
labeled ×3commented ×2

Error Message

Error Messages/Logs

No error or stack trace — it silently returns empty results.

Root Cause

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 prefixActual session dir keyMatch?
-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.

Code Example

> /resume
No conversations found to resume

---

mkdir parent && cd parent && git init
   git submodule add <repo-A-url> projects/repo-a
   git submodule add <repo-B-url> projects/repo-b

---

git worktree add ../repo-a--feature feature-branch

---

git worktree remove repo-a--feature

---

worktree /path/to/parent/.git/modules/projects/repo-a          ← NOT the actual checkout
worktree /path/to/parent/projects/repo-a--feature               ← secondary worktree

---

const currentWorktree = worktreePaths.find(
    path => cwd === path || cwd.startsWith(path + sep),  // both checks fail
)

---

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)
}

---

if (!currentWorktree) {
    return [cwd, ...otherWorktrees]
}
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • 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

  1. Create a parent repo with two submodules:

    mkdir parent && cd parent && git init
    git submodule add <repo-A-url> projects/repo-a
    git submodule add <repo-B-url> projects/repo-b
  2. cd projects/repo-a and run a few Claude Code sessions (sessions are saved normally).

  3. Create a secondary worktree inside repo-a:

    git worktree add ../repo-a--feature feature-branch
  4. Run /resume in projects/repo-a"No conversations found to resume"

  5. Verify projects/repo-b (no secondary worktree) → /resume works fine.

  6. Remove the worktree:

    git worktree remove repo-a--feature
  7. Run /resume in projects/repo-a again → 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 prefixActual session dir keyMatch?
-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)

extent analysis

TL;DR

Modify the getWorktreePaths() function to include the current working directory (cwd) when it doesn't match any parsed worktree path, to correctly handle submodules with secondary worktrees.

Guidance

  • Review the getWorktreePaths() function to ensure it correctly handles submodule paths, especially when a secondary worktree is present.
  • Consider adding a fallback to include the cwd in the worktree paths when no match is found, as suggested in the issue analysis.
  • Verify that the getStatOnlyLogsForWorktrees() function is correctly handling the case where multiple worktree paths are present.
  • Test the changes with a submodule that has a secondary worktree to ensure that sessions are correctly listed.

Example

if (!currentWorktree) {
    return [cwd, ...otherWorktrees]
}

This code snippet modifies the getWorktreePaths() function to include the cwd when no match is found, which should fix the issue with submodules and secondary worktrees.

Notes

The suggested fix is based on the analysis of the decompiled TypeScript source code, and may not be exactly the same as the official published source. Additionally, the issue may be specific to the Claude Code version 2.1.96 and the Anthropics API platform.

Recommendation

Apply the suggested fix to the getWorktreePaths() function to include the cwd when no match is found, as this should correctly handle submodules with secondary worktrees and allow sessions to be listed correctly.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING