[BUG] Start-up hangs forever (main thread in open()) when a permission rule's path resolves to a TCC-protected location and the process lacks access

Status Open
Reported on v2.1.289
Maintainer reply None cached
Activity 0 comments · opened Oct 5, 2026

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?

Claude Code appears to read the target of each Read(...) permission rule during start-up. If a rule's path resolves into a macOS privacy-protected (TCC) location, such as a folder on a removable volume, and the launching process has no access to it, the CLI's main thread blocks in open() waiting for a consent decision that a background process can never get.

  • The session never emits system/init and never starts its first turn. It waits forever.
  • Nothing is logged: the debug log simply stops.
  • Because the event loop is frozen, child processes it already spawned are never reaped. Ours was a git clone of the plugin marketplace, left as a zombie.

Reproduced on 2.1.289 (latest) and 2.1.281. 2.1.173 does not do this with the same configuration.

The minimal trigger is one rule, Read(//Users/<me>/backup/**), where ~/backup is a symlink to a folder on an external APFS drive. No MCP servers, plugins or hooks are needed. It was launched through the Agent SDK (@anthropic-ai/claude-agent-sdk 0.3.289, SDK mode) by a Node process under pm2: a background process without Full Disk Access, on macOS 15.4.1 (Apple silicon). The same query works from an SSH shell, because Remote Login has Full Disk Access.

What Should Happen?

Permission rules should not require reading the target's data at start-up. If resolution is needed, it should be one of:

  • metadata-only (lstat/readlink);
  • off the main thread, with a timeout, treating an unreadable target as "rule applies, target unreadable".

Either way, a rule pointing at an inaccessible location should never block the session, and failures should be logged.

Error Messages/Logs

Kernel log (log show --predicate 'eventMessage CONTAINS "System Policy: claude("'):
System Policy: claude(<pid>) deny(-1) file-read-data /Volumes/External/somedir
(becomes deny(4) once the hung process is killed)

tccd: a kTCCServiceSystemPolicyRemovableVolumes request attributed to the launching node process

sample <pid>: the main thread sits in openat$NOCANCEL -> __openat_nocancel for the whole sample; about 0.3 s of CPU in total

SDK message stream: with a string prompt, nothing at all; with streaming input, system/session_state_changed (running) and rate_limit_event (allowed), then nothing. Never system/init.

--debug-file: start-up proceeds normally (startupWorkGate opens), then stops right before the agents-md prompt.context hook and "[engine] turn 1 start"; nothing further is ever logged

Steps to Reproduce

  1. On macOS, create a symlink in your home folder to a folder on an external (removable) drive: ln -s /Volumes/External/somedir ~/link
  2. Save this as repro.mjs (Agent SDK 0.3.289, which bundles Claude Code 2.1.289):
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const m of query({
  prompt: "Reply with OK",
  options: { disallowedTools: ["Read(//Users/<me>/link/**)"] },
})) {
  console.log(m.type, m.subtype ?? "");
}
  1. Run it as a background process without Full Disk Access, for example pm2 start repro.mjs --no-autorestart or a launchd agent. Don't run it from Terminal or an SSH session, which have broader access.
  2. Nothing is printed, no system/init is emitted, and the process never exits. The kernel log shows System Policy: claude(<pid>) deny(-1) file-read-data /Volumes/External/somedir.
  3. Control: remove the disallowedTools rule, or run the same script from an SSH shell, and it completes in about 2 s.

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.173

Claude Code Version

2.1.289 (Claude Code), also reproduced on 2.1.281

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

_No response_

View original on GitHub ↗