claude-code - 💡(How to fix) Fix Plugin manager: `.in_use/<pid>` lock files leak when sessions crash [1 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#58881Fetched 2026-05-14 03:37:08
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Timeline (top)
cross-referenced ×2labeled ×2commented ×1

The plugin manager records active sessions holding a plugin version by writing empty files named after the session's PID into ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/.in_use/. When a Claude Code process exits ungracefully (crash, force-kill, OS reboot before clean shutdown), the corresponding .in_use/<pid> file is not removed. The plugin manager subsequently believes the orphaned version is still in use, so it cannot safely garbage-collect it.

Error Message

for pid_file in (cache_dir / ".in_use").iterdir(): try: pid = int(pid_file.name) except ValueError: pid_file.unlink(missing_ok=True) # malformed continue if not _pid_alive(pid): pid_file.unlink(missing_ok=True)

Root Cause

The plugin manager records active sessions holding a plugin version by writing empty files named after the session's PID into ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/.in_use/. When a Claude Code process exits ungracefully (crash, force-kill, OS reboot before clean shutdown), the corresponding .in_use/<pid> file is not removed. The plugin manager subsequently believes the orphaned version is still in use, so it cannot safely garbage-collect it.

Code Example

$ ls ~/.claude/plugins/cache/community-access/accessibility-agents/3.2.0/.in_use/
18792  2093  2320  23515  29905  36512  57707  63327

$ for pid in 18792 2093 2320 23515 29905 36512 57707 63327; do
    if kill -0 "$pid" 2>/dev/null; then
      echo "PID $pid: alive — $(ps -p $pid -o comm= 2>/dev/null)"
    else
      echo "PID $pid: STALE"
    fi
  done
PID 18792: alive — claude
PID 2093:  alive — claude
PID 2320:  STALE
PID 23515: alive — claude
PID 29905: STALE
PID 36512: STALE
PID 57707: STALE
PID 63327: STALE

---

for pid_file in (cache_dir / ".in_use").iterdir():
    try:
        pid = int(pid_file.name)
    except ValueError:
        pid_file.unlink(missing_ok=True)  # malformed
        continue
    if not _pid_alive(pid):
        pid_file.unlink(missing_ok=True)
RAW_BUFFERClick to expand / collapse

Plugin manager: .in_use/<pid> lock files leak when sessions crash

Summary

The plugin manager records active sessions holding a plugin version by writing empty files named after the session's PID into ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/.in_use/. When a Claude Code process exits ungracefully (crash, force-kill, OS reboot before clean shutdown), the corresponding .in_use/<pid> file is not removed. The plugin manager subsequently believes the orphaned version is still in use, so it cannot safely garbage-collect it.

Reproduction

Live evidence collected on 2026-05-13 from one machine that had been running Claude Code over a multi-week period:

$ ls ~/.claude/plugins/cache/community-access/accessibility-agents/3.2.0/.in_use/
18792  2093  2320  23515  29905  36512  57707  63327

$ for pid in 18792 2093 2320 23515 29905 36512 57707 63327; do
    if kill -0 "$pid" 2>/dev/null; then
      echo "PID $pid: alive — $(ps -p $pid -o comm= 2>/dev/null)"
    else
      echo "PID $pid: STALE"
    fi
  done
PID 18792: alive — claude
PID 2093:  alive — claude
PID 2320:  STALE
PID 23515: alive — claude
PID 29905: STALE
PID 36512: STALE
PID 57707: STALE
PID 63327: STALE

4 of 8 lock files (50%) were stale — referencing processes that had long since exited. This blocked the plugin manager from orphan-cleaning the v3.2.0 directory even after v4.0.0 was installed and orphan-flagged.

Proposed fix — two options

Option A: kernel-level advisory locks (flock(2))

Replace the .in_use/<pid> file convention with flock() against a single file per version. The kernel releases the lock on process exit regardless of how the process died.

  • Pros: correct by construction. No stale state possible.
  • Cons: requires a syscall path on Windows (or a Win32 LockFileEx equivalent). Slightly more code than the current file-touch convention.

Option B: stale-PID sweep on every cache read

Keep the file convention but add a sweep step before reading .in_use/:

for pid_file in (cache_dir / ".in_use").iterdir():
    try:
        pid = int(pid_file.name)
    except ValueError:
        pid_file.unlink(missing_ok=True)  # malformed
        continue
    if not _pid_alive(pid):
        pid_file.unlink(missing_ok=True)

_pid_alive() uses kill -0 <pid> on POSIX, OpenProcess on Windows. Cost: a few syscalls per cache operation. Risk: a freshly-spawned PID could collide with a recycled-PID stale entry — rare in practice (PID space is large) but worth noting.

  • Pros: minimal change. Drop-in replacement for the current convention.
  • Cons: still leaves a small window for stale entries between sweeps.

Recommendation

Ship Option B in the short term (low risk, immediate improvement). Plan Option A as a long-term cleanup once the cross-platform implementation cost is budgeted.

Acceptance

  • After force-killing a Claude Code process holding a plugin version, the next plugin-manager interaction (install/update/list) removes the stale .in_use/<pid> file for the dead PID.
  • A pid file referencing a PID that has been recycled to a non-Claude-Code process is treated as stale (the file is removed). Acceptable trade-off given the rarity.

See also

  • Companion issue: .orphaned_at flag has no garbage collector — #58880
  • Companion issue: plugin major-version updates that change agent count drastically should expose a post-update migration hook — #58882

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

claude-code - 💡(How to fix) Fix Plugin manager: `.in_use/<pid>` lock files leak when sessions crash [1 comments, 2 participants]