Regression (2.1.195 → 2.1.196): background daemon transient-spawn fails over SSH on macOS — "Could not switch to audit session: Operation not permitted"

Open 💬 3 comments Opened Jul 1, 2026 by Qythyx

Regression (2.1.195 → 2.1.196): background daemon transient-spawn fails over SSH on macOS — "Could not switch to audit session: Operation not permitted"

Environment

  • macOS, Apple Silicon
  • Running over SSH (VS Code Remote-SSH; sshd … @notty, SSH_CONNECTION set)
  • Regression introduced in 2.1.196; still present in 2.1.197. Last-good: 2.1.195.

Symptom

With no daemon already running, the REPL session switcher / background agents cannot cold-spawn the background daemon from an SSH session — it hangs, then reports:

Couldn't reach the background service (not running) — run 'claude daemon status'

claude -r and foreground interactive sessions are unaffected (they never spawn the daemon). The bug is masked whenever a daemon is already running, because SSH clients just attach to the existing one instead of cold-spawning. It only surfaces on the first cold spawn from an SSH session after the daemon idle-exits.

Root cause

The fatal error is only visible in the client stderr (the daemon dies before it can open ~/.claude/daemon.log), so it must be captured with --debug-file:

[ERROR] daemon: transient spawn stderr:
Could not switch to audit session 0x…: 1: Operation not permitted
[WARN] background spawn failed: Couldn't reach the background service (not running)

macOS denies the audit-session switch in an SSH notty context. The client-side daemon-spawn code appears to have changed between 2.1.195 and 2.1.196 to require this audit-session join.

Deterministic A/B repro

Over SSH. Force a transient spawn with --bg, running claude daemon stop --any before each run so there is no pre-existing daemon to attach to. Invoke specific versions directly (the version entry under ~/.local/share/claude/versions/<v> is the executable itself, not a directory):

claude daemon stop --any
~/.local/share/claude/versions/<version> --bg -p "hi" --debug-file /tmp/x.debug

Results, repeated A/B/A/B, every run starting from daemon status = not running:

| Client version | audit-session error | result |
| -------------- | ------------------- | -------------------------------------------------------------------- |
| 2.1.195 | none | ✓ backgrounded; daemon log shows daemon start … origin=transient |
| 2.1.196 | yes | ✗ Couldn't reach the background service |
| 2.1.197 | yes | ✗ Couldn't reach the background service |

The daemon binary launched is identical (the 2.1.197 default) in all three cases — only the spawning client version differs. This isolates the regression to the client-side daemon-spawn path between 2.1.195 → 2.1.196.

Workarounds

  • Keep a daemon alive so SSH clients attach instead of cold-spawning: claude daemon run in a spare terminal/tmux (foreground origin works fine over SSH), or seed the daemon once from a GUI-session launch / the Desktop app.
  • Pin to 2.1.195.

Asks

  1. Restore ≤2.1.195 spawn behavior over SSH — don't require an audit-session switch for the transient daemon spawn, or fall back gracefully when it's denied.
  2. Fail fast with an accurate message instead of a long hang followed by the misleading "background service (not running)"; surface the underlying Operation not permitted to the user, not just to --debug-file.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗