[BUG] Slash commands only load first file on ExFAT filesystems due to JavaScript Number precision loss
Summary
Claude Code v2.0.69 only discovers one slash command from .claude/commands/ on ExFAT-formatted drives, despite multiple .md files being present. This is a silent failure - no error messages, remaining commands simply don't load.
Root Cause
JavaScript Number type cannot represent ExFAT's 64-bit inodes precisely (53-bit precision limit). All inodes round to the same value, causing inode-based deduplication to treat distinct files as duplicates.
Debug logs show:
[DEBUG] Skipping duplicate file 'second.md' (same inode already loaded)
[DEBUG] Skipping duplicate file 'third.md' (same inode already loaded)
Actual inode values:
$ stat -f "%N: inode %i" /Volumes/LaCie/.claude/commands/*.md
first.md: inode 18446744073709450884
second.md: inode 18446744073709450881 # DIFFERENT
third.md: inode 18446744073709450878 # DIFFERENT
Node.js without BigInt (broken):
const stats = fs.statSync('first.md');
console.log(stats.ino); // 18446744073709451000
const stats2 = fs.statSync('second.md');
console.log(stats2.ino); // 18446744073709451000 (SAME - precision lost!)
All inodes > 2^53 round to the same Number value.
The Fix
Add { bigint: true } to all fs.statSync() calls in file loading code:
// BEFORE (broken):
const stats = fs.statSync(filePath);
const inode = stats.ino;
// AFTER (fixed):
const stats = fs.statSync(filePath, { bigint: true });
const inode = stats.ino.toString(); // BigInt preserves precision
Affected areas:
- Slash command loading (
.claude/commands/) - Agent loading (
.claude/agents/) - Skill loading (
.claude/skills/) - Any file discovery using
stats.inofor deduplication
Reproduction Steps
Prerequisites: ExFAT-formatted external drive
# 1. Create test directory on ExFAT drive
mkdir -p /Volumes/YOUR_EXFAT_DRIVE/.claude/commands
# 2. Create multiple command files
printf '%s\n' '---' 'description: First' '---' '# First' > /Volumes/YOUR_EXFAT_DRIVE/.claude/commands/first.md
printf '%s\n' '---' 'description: Second' '---' '# Second' > /Volumes/YOUR_EXFAT_DRIVE/.claude/commands/second.md
printf '%s\n' '---' 'description: Third' '---' '# Third' > /Volumes/YOUR_EXFAT_DRIVE/.claude/commands/third.md
# 3. Start Claude Code
cd /Volumes/YOUR_EXFAT_DRIVE
claude
# 4. Check commands
/help # Only shows /first - /second and /third missing!
Expected: All 3 commands appear
Actual: Only first command appears, others silently skipped
Impact
Severity: CRITICAL
Affected systems:
- ✅ ExFAT (external drives, USB sticks) - CONFIRMED on macOS
- ⚠️ FAT32 - Likely affected (same inode behavior)
- ❓ NTFS - Unknown (64-bit inodes, needs testing)
- ✅ APFS/HFS+/ext4 - NOT affected (inodes < 2^53)
Cross-platform: Likely affects Windows and Linux (Node.js behavior is consistent)
Affected features:
- Multiple slash commands
- Multiple agents
- Multiple skills
- Any multi-file discovery using inode deduplication
Workaround
Option 1: Move project to APFS/internal drive (Mac)
cp -R /Volumes/ExFATDrive/project ~/Desktop/project
cd ~/Desktop/project
claude
Option 2: Use subdirectories (works despite bug)
mkdir -p .claude/commands/db
mv .claude/commands/*.md .claude/commands/db/
# Commands become namespaced (e.g., /db:command-name)
Environment
- Claude Code: v2.0.69
- OS: macOS Sequoia 15.5 (24F74)
- Filesystem: ExFAT (external drive)
- Node.js: v25.2.1 (bundled)
- Mount: fskit, noatime, noowners
Additional Notes
- Node.js 10.5.0+ required for
{ bigint: true }option (already met by Claude Code v2.0.69) - BigInt returns signed values (may appear negative for high inodes) - this is correct, values remain unique
- macOS Sequoia moved ExFAT to user-space (fskit), which may contribute to high inode values
- No related issues found mentioning ExFAT or inode precision
---
17 Comments
This is a (pretty bloody big) problem in windows as well; I'm getting Skill load failures specifically:
"Skipping duplicate skill 'X' from projectSettings (same inode already loaded from projectSettings)" - even though the files have unique NTFS file IDs.
The issue is caused by JavaScript floating-point precision loss when
fs.statSync()returns inode values as regular numbers instead of BigInts.Claude generated report details follow:
Environment
Reproduction
.claude/skills/(e.g., 30+ skill folders)NTFS file IDs are 64-bit integers. When files are created sequentially, they receive sequential file IDs. In my case:
Node.js
fs.statSync()returnsinoas a JavaScript number (IEEE 754 double). While these values are belowNumber.MAX_SAFE_INTEGER, doubles can only represent ~15-17 significant digits accurately. These 19-digit numbers lose precision in the last few digits:Proof via Node.js:
Debug Log Evidence
Suggested Fix
Use
{bigint: true}option when callingfs.statSync()for inode comparison:This option is available in Node.js 10.5.0+ and returns
inoas a BigInt, preserving full 64-bit precision.Workarounds
None that are practical. The inode values are determined by NTFS and cannot be controlled by users. Recreating files might land them in a different range, but this is not reliable.
Impact
Bumping this thread to say we're seeing the exact same issue across multiple users on our Alma Linux 9 based machines with home directories that are on NFS mounts. The symptoms are the same as described here by @Valriz and @leonardkore: the debug log shows incorrectly that multiple skills and/or slashcommands have the same inode, and have been deduplicated. As a result they do not load and are not available in the Claude Code session. Based on the two previous reports, this issue seems to affect any platform, MacOS, Windows, or Linux (which I am confirming with this post).
This is a critical issue for our power users who are developing Skills and SlashCommands in advance of rolling out Claude Code more broadly to our company. We can try rolling back to a version <2.0.69 or suggesting the nested directory workaround temporarily until this is resolved, but we'd love a real fix for this, so we can take advantage of all the great features and work that's gone into the more recent releases.
Additional debugging with Claude Code found that as a workaround symlinking the skills and commands directory to a filesystem (in my case /tmp) which has less that the overflow number of inodes gets around the issue, but not in a sustainable way that we can roll out across the company.
Further analysis from Claude below largely echoes what the previous authors already mentioned:
Claude Code Skill Deduplication Bug on NFS with 64-bit Inodes
Date: 2025-12-28
Claude Code Version: 2.0.76
Platform: Linux (RHEL 9), NFS filesystem
Node.js Version: v24.3.0
Status: Confirmed, workaround available
Summary
Claude Code incorrectly skips loading valid skills, reporting them as "duplicates" with identical inodes, when the filesystem inodes are actually unique. This occurs on NFS filesystems using 64-bit inode numbers that exceed JavaScript's
Number.MAX_SAFE_INTEGER.Evidence
Debug Log Shows Incorrect Deduplication
Result: Only 4 skills available (
orchestra-skill,wiki-edit,skill-creator,agent-sdk-dev:new-sdk-app).Missing:
wiki-search,code-search,hello,jr/jr-code-review.Filesystem Inodes Are Actually Unique
All 7 inodes are distinct at the filesystem level.
Node.js Reads Correctly But With Precision Loss
Despite IEEE 754 float64 precision loss (
Number.MAX_SAFE_INTEGER = 2^53 - 1 = 9,007,199,254,740,991), the resulting values remain unique - there are no actual collisions.No Collisions in Isolated JavaScript Tests
Map and Set operations work correctly with these values in isolation.
Workaround (Confirmed Working)
Sync skills to a local filesystem with smaller inode numbers and symlink from
~/.claude/.Test Results
| Configuration | Inode Range | Skills Loaded | Status |
|--------------|-------------|---------------|--------|
| NFS (original) | ~9×10^18 | 4 of 7 | BUG |
| Local XFS | ~10^8 | 7 of 7 | OK |
Workaround Script
Save as
~/.claude/sync-skills-to-local.sh:Usage
Verification
After applying the workaround:
Root Cause Analysis
Key Finding: Upper 32-Bit Collision Pattern
Analysis of the inode structure reveals a critical pattern:
All skipped skills share the same upper 32 bits (
0x806efa17), while loaded skills each have unique upper 32 bits. This suggests the deduplication logic may be:Likely Buggy Code Pattern
The collision pattern strongly suggests code like:
Note on JavaScript bitwise operators: All bitwise operators (
>>,<<,|,&,^) convert operands to 32-bit signed integers first. Usinginode >> 32on a 64-bit value does NOT extract the upper 32 bits—it produces garbage because the 64-bit value is truncated to 32 bits before shifting.System Context
Possible Root Causes
Math.floor(inode / 2^32)as dedup keyinode >> 32(JavaScript bitwise is 32-bit only)device:inodekey but truncating inodeWhy NFS Inodes Have This Structure
NFS 64-bit inodes typically encode filesystem metadata in the upper bits:
Files on the same NFS volume/server frequently share identical upper 32 bits, differing only in lower bits. Any deduplication logic that ignores or truncates the lower 32 bits will cause false collisions.
What's NOT the cause
Recommended Fix for Claude Code
Use BigInt for exact inode handling:
Reproduction Steps
~/.claude/skills/--debug) showing skills skipped as "same inode"stat -c '%i'that filesystem inodes are actually uniqueImpact
This is impacting us as well on NFS. The workaround until this gets fixed
I hit the exact same issue in NFS: some skills were missing due to deduplication based on "identical" inodes.
Workaround: copy files until they get non overlapping inodes.
@whyuan-cc : would it be possible to get an update on this bug as well? You were supremely helpful in updating us on the closed out issue here: https://github.com/anthropics/claude-code/issues/11912.
I was expecting to see this one in 2.1.1 today, looks like it still has issues. From the number of github-actions referencing this issue, it seems many folks are running into this.
Thanks so much!
Thanks for reporting. I have a PR to fix this.
This was fixed. Please reopen if you can repro with build this week.
may we know when will this be released? It is quite painful for NFS users...
@whyuan-cc based on CHANGELOG, this should be fixed in 2.1.3, but I am still seeing same issue in 2.1.12 for Linux build. Can you help to check the repo head?
@hongping could you kindly run
@whyuan-cc sure. I will update the output once I able to access my laptop. But just one observation, I don't see this problem when running Claude Code by installing through npm. However, if I install Claude Code through native install (the curl thingy), the issue persist.
@whyuan-cc based on the native build claude-2.1.12-linux-x64, the lstatSync.*bigint is there but issue persist. Based on debug log, it is complaining the inode is the same for the second md file in ~/.claude/commands.
stat -c '%i' ~/.claude/commands/* show
9275036499177641659
9275036499148460796
npm installation of claude code does not show the issue.
thanks for confirming. It is native build issue and we will fix it.
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
@whyuan-cc this issue is still persistent on claude code 2.1.66
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.