Skip to content

Hooks fail with posix_spawn ENOENT when session cwd is deleted; request fallback cwd before spawning hooks #65378

Description

@Nickcom4

Summary

When Claude Code spawns a hook, it appears to use posix_spawn('/bin/sh', ..., {cwd: <session_cwd>}). If <session_cwd> no longer exists at spawn time (common when a session was started inside a git worktree that has since been removed, or any directory deleted out from under a live session), the spawn fails with ENOENT before the hook body runs. Every hook for that event then dies identically, silently disabling the hook layer for the rest of the session.

Repro

  1. Start a session with cwd inside a directory that can be deleted (e.g. a git worktree).
  2. Delete that directory while the session is live (e.g. a worktree-cleanup step, a branch reaper, a concurrent process).
  3. Trigger any hook event (Stop, PreToolUse, etc.).

Observed: posix_spawn '/bin/sh' ... ENOENT; the hook never executes.

Why user-side mitigation cannot fully fix it

A common workaround is to cd "$HOME" at the top of each hook body when the cwd is gone. This cannot help here: the failure is at posix_spawn time, before the hook body (the /bin/sh invocation) starts, so no in-body recovery code ever runs. The only complete fix is in the harness: resolve a guaranteed-existing fallback cwd (e.g. $HOME, or the repo root, or the directory the Claude Code binary was launched from) before posix_spawn-ing a hook when the recorded session cwd no longer exists.

Request

Before spawning a hook, if the recorded session cwd does not exist, fall back to a known-good directory ($HOME or launch dir) rather than passing a deleted path to posix_spawn. This keeps the hook layer alive across directory-deletion races instead of silently disabling it.

Context

Witnessed repeatedly with worktree-based workflows where cleanup automation removes the worktree a session is sitting in; all Stop hooks for the session failed identically with the recover-cwd lib already sourced at their top (which, per the above, cannot help). Filing as the upstream half of a tracked downstream issue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:hooksbugSomething isn't workingreproducedBug reproduced by maintainers on a released build

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions