Atomic file writes fail with multi-level symlinks (nix home-manager)
Resolved 💬 4 comments Opened Dec 30, 2025 by andrewgazelka Closed Feb 21, 2026
Description
Claude Code only resolves one level of symlinks when performing atomic file writes. When using nix home-manager with mkOutOfStoreSymlink, this creates a multi-level symlink chain through the read-only nix store, causing repeated EACCES errors on startup.
Symlink chain
~/.claude.json
→ /nix/store/...-home-manager-files/.claude.json
→ /nix/store/...-hm_.claude.json
→ /Users/user/.config/nix/claude/global/.claude.json (writable!)
Current behavior
Claude Code resolves only the first symlink level, sees the target is in /nix/store/, then tries to create a temp file there for atomic write:
Writing through symlink: ~/.claude.json -> /nix/store/...-home-manager-files/.claude.json
Writing to temp file: /nix/store/...-home-manager-files/.claude.json.tmp...
Failed to write file atomically: EACCES: permission denied
Falling back to non-atomic write
This happens multiple times during startup (adds noise to debug logs and likely minor latency).
Expected behavior
Claude Code should use realpath() (equivalent to readlink -f) to fully resolve the symlink chain to the actual writable file before determining the temp file directory.
Environment
- macOS (Darwin 25.2.0)
- Claude Code v2.0.76
- nix with home-manager using
mkOutOfStoreSymlink
Reproduction
- Use nix home-manager to manage
~/.claude.jsonwithmkOutOfStoreSymlink - Run
claude --debug - Observe repeated EACCES errors in debug log for atomic write attempts
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗