All project hooks silently disappear for the rest of a session after the project's volume dismounts and remounts (Windows, Google Drive for desktop)

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

Environment

  • Claude Code 2.1.291 (first A/B run) and 2.1.292 (second A/B run, the latest release at filing)
  • Windows 11 Pro 25H2 (10.0.26200), Git Bash
  • Google Drive for desktop 131.0.2.0 in stream mode; the project lives on its virtual drive (H:\My Drive\<project>)
  • The project's hooks are in .claude/settings.json (and permissions in .claude/settings.local.json)

What happens

When the Drive volume dismounts and remounts while a session runs, every hook from the project's .claude/settings.json stops running for the rest of that session. This happens after a sleep/wake that remounts Drive, after a Drive self-restart, and after a Drive update. There is no hook error notice: the hooks are simply gone. Editing .claude/settings.json later in the same session does not bring them back. Restarting the session (--resume) does.

Measured on one machine over two weeks: 9 of 9 sessions used after a Drive remount lost every hook. 23 of 23 sessions woken from sleep without a remount kept them.

This defeats the purpose of hooks used as guardrails: they switch off silently, and nothing in the session tells you.

What we think happens

  1. When the volume disappears, Claude Code fires ConfigChange for project_settings and local_settings, and the files do not exist at that moment. It applies this as empty project and local settings.
  2. When the volume comes back, no further ConfigChange arrives and the settings are never re-read. The settings watcher seems to die with the volume and is not re-armed.

For contrast, on a local NTFS disk, deleting .claude/settings.json mid-session also empties the hook list. But re-creating the file fires ConfigChange again and the hooks come back about 10 s later. So the unrecoverable part is specific to the volume going away.

A/B evidence (one real Drive restart, n = 1 per arm)

We ran two fresh headless sessions in the same Drive project, same prompt (echo before, wait for the drive to drop and return, echo after1, echo after2). Session A also loaded, from a --settings file on C:, a ConfigChange hook (matcher project_settings|local_settings). That hook returns {"decision":"block"} when the event's file_path no longer exists.

Counts are hook-log lines (one at the start and one at the end of each hook run):

| | Before the drop | ConfigChange at the drop (+2 s) | After the remount |
|---|---|---|---|
| A (guard) | 20 PreToolUse (plus SessionStart) | local_settings and project_settings, both file_path missing → blocked | 20 PreToolUse, 18 Stop, 2 SessionEnd |
| B (control) | 20 PreToolUse (plus SessionStart) | (no observer) | 0 |

The drive letter was absent for about 40 s. While it was absent, the hook scripts (which also live on the drive) could not start, which is expected. Once it returned, they ran again in A only.

A second run on the same day with the guard registered in user settings (~/.claude/settings.json, "timeout": 15) instead of a --settings file gave the same result. Session A loaded default setting sources; the control loaded --setting-sources project,local. The drive was gone for about 50 s. A's guard blocked both events 2 s after the drop, and A logged 20 PreToolUse, 18 Stop and 2 SessionEnd hook lines after the remount. The control logged 0. An interactive session that was already running picked up the user-settings guard without a restart, and kept its hooks through the same restart.

Side note: in the same restart, the session's project-level agent types (from .claude/agents/ on the drive) dropped out of its agent list while the drive was gone. They were re-listed about 2 minutes after it returned, so this is a transient gap, not a loss; a subagent of those types started inside that window would fail.

Minimal repro

  1. On Windows, use Google Drive for desktop in stream mode, with a project folder on the Drive letter.
  2. Give the project .claude/settings.json a PreToolUse hook (matcher Bash) that appends a line to a log on C:.
  3. Start claude in the project and run any Bash command. The log gets a line.
  4. In the tray, quit Google Drive for desktop, then relaunch it. The drive letter disappears for about 30-40 s and comes back.
  5. Run a Bash command. No log line. Edit .claude/settings.json: still none. claude --resume: lines again.

Optional, to see the event: a ConfigChange hook in ~/.claude/settings.json that logs its stdin shows source=project_settings / local_settings with the file missing at the moment of the dismount.

Not tested, but probably the same: any volume that can vanish under a session (a detached VHD, a disconnected mapped network drive, a USB disk).

Expected

Any of these would fix it:

  • Do not apply "settings file missing because its whole volume vanished" as an empty-settings change. Or re-check after a short delay before applying a deletion.
  • When the watched path becomes available again, re-arm the watcher and re-read the settings.

Workaround we use

A ConfigChange hook in user settings (on a local disk, so it runs while the volume is gone). It blocks a project_settings / local_settings change whose file_path does not exist:

// node, stdin = the ConfigChange event
let s = ''; process.stdin.on('data', d => s += d).on('end', () => {
  const j = JSON.parse(s);
  if (['project_settings', 'local_settings'].includes(j.source) && j.file_path && !require('fs').existsSync(j.file_path))
    process.stdout.write(JSON.stringify({ decision: 'block', reason: 'settings file vanished (volume dismount?)' }));
});

The cost of this workaround is that a deliberate mid-session delete of a settings file is not applied until restart.

Possibly related

  • #95440: a FileChanged hook stops firing after a cwd change (also a watcher that is not re-armed).
  • CHANGELOG 2.1.205: a Windows crash when the launch directory is deleted, locked or unmounted. 2.1.222 / 2.1.229: file-watcher errors and teardown, and a Windows watcher failure on a network or virtual filesystem. 2.1.271: a macOS settings-watcher polling fallback. A recent entry also fixes Linux sandboxed Bash running ConfigChange hooks and reloading settings when .claude/settings.json does not exist. We found no entry for re-arming the settings watcher after a volume returns, up to 2.1.292.

View original on GitHub ↗