[BUG] Task tools' per-session lockfile fails with EPERM (`utimensat`) when CLAUDE_CONFIG_DIR is on an SMB/CIFS mount (e.g. Azure Files)

Open 💬 0 comments Opened Jul 11, 2026 by laskey

Environment

  • Claude Agent SDK (Python) ≥ 0.2.110, bundled CLI ≥ 2.1.142 (still present on current versions)
  • Linux container (Azure Container Apps), CLAUDE_CONFIG_DIR pointed at a volume backed by Azure Files (SMB / CIFS mount)
  • Headless SDK usage (bypassPermissions)

Bug

Since the in-session task tool flipped from TodoWrite to the structured
TaskCreate/TaskUpdate/TaskList/TaskGet family (CLI 2.1.142), each
session maintains a lockfile at:

{CLAUDE_CONFIG_DIR}/tasks/<session-id>/.lock.lock

The lock implementation calls utimensat(2) on this file (touch-style
timestamp update). On a CIFS/SMB mount this fails with EPERM — the
Linux CIFS client rejects the timestamp update even though the process
owns the file and the mount is read-write. Task tool calls then error out
for the whole session.

Plain file writes (including the session JSONL transcripts in the same
config dir) work fine on the same mount — it's specifically the
timestamp-update step of the lock protocol that trips.

Repro

  1. Mount an Azure Files share (or any CIFS mount) and set

CLAUDE_CONFIG_DIR to a directory on it.

  1. Run any SDK session and let the model call TaskCreate.
  2. Observe EPERM from utimensat on tasks/<session>/.lock.lock; task

tools unusable for the session.

Minimal isolation without the SDK: touch f && python3 -c "import os;
os.utime('f')"
on the CIFS mount reproduces the EPERM for the same class
of mount options.

Workaround we're riding

CLAUDE_CODE_ENABLE_TASKS=0 (the documented back-compat knob) to keep
TodoWrite. Works, but it pins us to the legacy tool family and we'd
like to adopt the Task tools.

Suggested fixes (any one would unblock)

  • Tolerate EPERM/ENOTSUP from the timestamp-update step of the lock

protocol (fall back to write-based liveness, or treat as advisory), or

  • Make the tasks/lock directory location independently configurable

(e.g. CLAUDE_TASKS_DIR) so it can point at local ephemeral disk while
the config dir stays on the share, or

  • Use an O_EXCL-create + unlink lock scheme that avoids utime entirely.

Related precedent: 2.1.181's changelog fixed Write/Edit producing
0-byte/truncated files on network drives — this is the same substrate
class (SMB semantics), one layer up in the lock protocol.

View original on GitHub ↗