[BUG] Native installer/updater fails with EEXIST mkdir when XDG dirs live in a OneDrive sync root (orphaned Files-On-Demand placeholders)
What's Wrong?
The native Windows installer (irm https://claude.ai/install.ps1 | iex) and claude update fail with EEXIST on mkdir when the XDG directories (~/.local/share, ~/.local/state) live inside a OneDrive Files-On-Demand sync root — in my case via a directory symlink %USERPROFILE%\.local → C:\Users\<user>\OneDrive\.local, used intentionally to sync dotfiles across desktops.
The failing directories are orphaned cloud placeholders: they show up in the parent directory listing with reparse tag 0x9000E01A (cloud files), but cannot be stat'ed — Get-Item/Remove-Item/attrib all report "path not found" for the same entry that dir lists. Node's fs.mkdirSync(p, {recursive: true}) then hits the contradiction: mkdir returns EEXIST, the follow-up stat fails, so it throws EEXIST and the installer aborts.
Key facts verified on the affected machine:
- A healthy OneDrive placeholder is not the problem. A freshly created directory inside the sync root is converted to a placeholder (tag
0x9000E01A) within ~5 seconds, andfs.mkdirSync({recursive: true})succeeds on it — both through the symlink path and the direct path. - Only the orphaned state breaks installation (listed in parent enumeration,
ENOENTon stat). These orphans appeared after the items had been deleted on the cloud side (including emptying the OneDrive recycle bin); the deletion never fully applied to the local placeholders. - While the sync state was wedged, local remediation was reverted within seconds:
rd /s /q+ recreate as a real directory +attrib +P("Always keep on this device") — the sync engine put the broken placeholder back, and the next install attempt failed identically. - The hint printed by the installer,
Try running with --force to override checks, does not help: the install script does not forward a--forceflag, and running the downloaded binary withclaude.exe install --forcemanually fails with the sameEEXIST.
What Should Happen?
- Diagnose the contradictory state. When
mkdirreturnsEEXISTbut the same path cannot be stat'ed, the installer/updater should print an actionable message (cloud-placeholder / wedged OneDrive sync state, with remediation such as resetting the OneDrive sync database) instead of a bareEEXISTplus a misleading--forcehint. - Ideally, attempt remediation: remove the orphaned directory entry and retry the
mkdir, or create the tree under a temporary name and rename into place. - Consider machine-local placement for per-machine runtime state.
~/.local/state/claude/locksis inherently machine-local; placing it under a user-synced XDG tree invites both this failure mode and lock files syncing between machines. Mapping~/.localinto OneDrive for cross-desktop dotfile sync is a deliberate, long-term setup — "move your XDG dirs out of OneDrive" is a workaround, not an acceptable requirement.
Error Messages/Logs
PS> irm https://claude.ai/install.ps1 | iex
Setting up Claude Code...
Checking installation status...
Installing Claude Code native build latest...
× Installation failed
EEXIST: file already exists, mkdir '%USERPROFILE%\.local\share\claude\versions'
Try running with --force to override checks
Write-Error: Installation failed (exit code 1)
PS> claude update
Current version: 2.1.173
Checking for updates to latest version...
Error: Failed to install native update
Error: EEXIST: file already exists, mkdir '%USERPROFILE%\.local\state\claude\locks'
Try running "claude doctor" for diagnostics
Diagnostic signature of the orphaned placeholder (same entry, contradictory answers):
PS> cmd /c dir /A "%USERPROFILE%\.local\share\claude\versions"
2026-06-12 08:08 0 2.1.173 <- listed by enumeration
PS> Get-Item "%USERPROFILE%\.local\share\claude\versions\2.1.173"
Get-Item: Cannot find path '...' because it does not exist. <- stat fails
PS> fsutil reparsepoint query "%USERPROFILE%\.local\share\claude\versions"
Reparse Tag Value : 0x9000e01a <- cloud placeholder
Control experiment showing healthy placeholders are fine:
PS> node -e "require('fs').mkdirSync('%USERPROFILE%/.local/share/test-dir', {recursive:true})"
(succeeds — even though fsutil shows the same 0x9000e01a tag on the directory)
Steps to Reproduce
A deterministic repro is hard because it requires the OneDrive sync state to be wedged; the diagnostic signature above is the reliable identifier. The sequence that produced it here:
- Windows 11, OneDrive with Files-On-Demand enabled.
mklink /D %USERPROFILE%\.local %USERPROFILE%\OneDrive\.local(cross-desktop dotfile sync).- Install Claude Code natively;
~/.local/share/claude/...and~/.local/state/claude/...are created inside the sync root and become cloud placeholders. - The
claudedirectories get deleted on the cloud side (e.g. from another machine or the web UI, recycle bin emptied) while the local client holds placeholders. - Local result: orphaned placeholder entries (listed in parent,
ENOENTon stat). - Run the install script or
claude update→EEXIST: file already exists, mkdir ....
Workaround that fixed it durably: point the XDG variables outside the sync root (XDG_DATA_HOME/XDG_STATE_HOME → %LOCALAPPDATA%\xdg\...) — confirmed the installer and updater honor these. But this defeats the purpose of syncing ~/.local across desktops, hence this report.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Claude Code Version
2.1.173 (Claude Code), native win32-x64
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
- Existing open
EEXISTissues (#67408, #60006, #59622, #66205) all concern non-idempotentmkdirof~/.claudesubdirectories at runtime — different paths and a different root cause (those reproduce with healthy directories; this one requires the orphaned-placeholder state in the native install tree under~/.local). ~/.local/bin/claude.exe(the self-contained launcher) also lives inside the sync root in this setup; it currently works with the pinned (+P) attribute, but the same orphaned-placeholder failure mode presumably applies to launcher replacement during updates.