[BUG] /export fails with EEXIST on Windows when the target directory has the ReadOnly attribute (Bun mkdir recursive bug — root cause + 1-line fix)
Bug Description
/export (with or without a filename argument) fails on Windows native builds:
❯ /export
⎿ Failed to export conversation: EEXIST: file already exists, mkdir 'C:\Users\<user>\Documents\<project>'
The path in the error is the session CWD — the directory that already exists and should be a no-op for a recursive mkdir.
This is a re-report of #52161, which was closed as stale by the bot without a fix. It still reproduces on the latest version (2.1.218). This report adds the verified root cause.
Root cause (verified)
The export code itself is correct — it calls fs.promises.mkdir(path.dirname(target), { recursive: true }), which per Node semantics must succeed silently when the directory exists.
The bug is in Bun, the runtime the native Windows binary is compiled with: on Windows, mkdir(..., { recursive: true }) throws EEXIST when the existing directory carries the ReadOnly attribute. Plain directories are unaffected.
- Upstream bug: oven-sh/bun#34413 (fix merged upstream 2026-07-16, not yet in a Bun release bundled by Claude Code), also oven-sh/bun#29521.
- Reproduced independently of Claude Code with plain Bun 1.3.1 on Windows 11:
// dir exists and has the ReadOnly attribute (attrib +R) — e.g. anything OneDrive-synced,
// Windows special folders like Documents, or folders stamped R by sync/backup tools
await require('fs/promises').mkdir('C:/Users/x/Documents', { recursive: true });
// Bun: EEXIST — Node: resolves undefined
This is why the bug looks intermittent across users/machines: it only bites when the session CWD (or the export target's parent) happens to have the R attribute — which OneDrive sets on everything it syncs, so OneDrive users are hit hardest (matches the OneDrive path in #52161).
Reproduction
- Windows, native install.
attrib +R .in any project directory (or use any OneDrive-synced dir).- Run
claude, then/export anything.txt→EEXIST. attrib -R .→/exportworks.
Suggested fix
Same guard already applied for the identical Bun bug in the session-env mkdir (#59622): wrap the export-path mkdir so an existing directory can't fail —
if (!existsSync(dir)) await mkdir(dir, { recursive: true });
// or: await mkdir(dir, {recursive:true}).catch(e => { if (e.code !== 'EEXIST') throw e; })
Longer term, bumping the bundled Bun to a release containing the fix for oven-sh/bun#34413 removes the whole class of Windows EEXIST bugs.
Environment Info
- Platform: win32 (Windows 11)
- Terminal: windows-terminal
- Version: 2.1.218 (native)
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗