Skip to content

Bug: daemon caches resolved binary path across Claude upgrades (stale symlink) #120

@c-h-

Description

@c-h-

What happened

After upgrading Claude Code from 2.1.52 to 2.1.70, the agentctl daemon kept trying to spawn /Users/ms/.local/share/claude/versions/2.1.52 — the path it resolved at startup. New session launches failed with:

[claude-code] spawn error: spawn /Users/ms/.local/share/claude/versions/2.1.52 ENOENT

The symlink at ~/.local/bin/claude correctly pointed to 2.1.70, but the daemon's in-memory cache (resolvedCache in resolve-binary.ts) held the old resolved realpath from when it first started.

What was expected

The daemon should either:

  1. Clear the binary cache on each launch (not just daemon restart), or
  2. Re-resolve symlinks periodically (e.g., on spawn failure), or
  3. Not resolve through symlinks at all — spawn the symlink path directly and let the OS resolve it

How to reproduce

  1. Start agentctl daemon with Claude Code 2.1.52 installed
  2. Upgrade Claude Code to 2.1.70 (symlink updates, old binary may or may not remain)
  3. Try agentctl launch claude-code — fails with ENOENT for old version path

Workaround

agentctl daemon restart clears the in-memory cache and re-resolves to the current symlink target.

Root cause

src/utils/resolve-binary.ts calls fs.realpath() to resolve symlinks, then caches the result in a Map for the daemon's lifetime. The cache is never invalidated except on process restart. clearBinaryCache() exists but is never called.

Proposed fix

Option A (simplest): On ENOENT spawn error, call clearBinaryCache() and retry once.
Option B: Don't realpath() — just verify the symlink is executable and spawn it directly.
Option C: Call clearBinaryCache() before each launch.

Environment

  • agentctl: latest (linked from ~/personal/agentctl)
  • macOS Darwin 25.2.0 arm64
  • Claude Code upgraded 2.1.52 → 2.1.70

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions