< Back to all hacks

#31 npm Cache on ext4

Debloat
Problem
FAT32/sdcardfs can't handle deep nested paths that git creates during npm install.
Solution
Move npm cache inside rootfs (ext4): npm config set cache /root/.npm-cache
Lesson
FAT32's 255-char path limit silently corrupts npm installs. ext4 has no practical limit.

Context

Hack #6 moved the npm cache to the SD card (/sdcard/npm-cache) to free internal storage. This worked for most packages, but git-based dependencies caused intermittent failures. When npm resolves a dependency from a git URL (e.g., github:user/repo#branch), it clones the repository into the cache directory, creating deep .git/objects/ hierarchies with paths like:

/sdcard/npm-cache/_cacache/content-v2/sha512/ab/cd/.git/objects/pack/pack-abc123...456.idx

These paths easily exceed the 255-character limit imposed by FAT32 via Android's sdcardfs FUSE layer. The result is ENAMETOOLONG errors that cause npm install to fail midway, leaving a corrupted cache that requires manual cleanup.

The /data partition where Termux lives is ext4, which supports path components up to 255 characters each and total paths limited only by the kernel's PATH_MAX of 4096 characters. Moving the cache there eliminates the problem entirely.

This hack supersedes Hack #6 (npm cache on SD card).

Implementation

Inside the proot Ubuntu rootfs (or native Termux, same principle):

# Set npm cache to a directory on the ext4 /data partition
npm config set cache /root/.npm-cache

# Create the directory
mkdir -p /root/.npm-cache

# Verify the new setting
npm config get cache
# Expected: /root/.npm-cache

# Clean the old SD card cache (optional, frees SD card space)
rm -rf /sdcard/npm-cache

For the native Termux setup (post proot migration):

# Native Termux equivalent — cache inside Termux's home
npm config set cache $HOME/.npm-cache

# Or use a path under $PREFIX/tmp for ephemeral caching
npm config set cache $PREFIX/tmp/.npm-cache

To verify the cache location is being used during installs:

# Run an install and watch where cache files land
npm install -g openclaw --ignore-scripts --legacy-peer-deps --cache /root/.npm-cache

# Check cache contents after install
ls /root/.npm-cache/
# Expected: _cacache/ _logs/ _npx/ etc.

# Check cache size
du -sh /root/.npm-cache/
# Expected: 200-400 MB depending on packages installed

Verification

# Confirm npm is configured correctly:
npm config get cache
# Expected: /root/.npm-cache (or $HOME/.npm-cache)

# Test with a git dependency that previously failed on FAT32:
npm cache clean --force
npm install some-git-dep@github:user/repo --cache /root/.npm-cache
# Expected: installs without ENAMETOOLONG

# Verify no files remain on SD card:
ls /sdcard/npm-cache 2>&1
# Expected: "No such file or directory" (if cleaned)

# Check filesystem type to confirm ext4:
mount | grep /data
# Expected: /dev/block/... on /data type ext4 ...

Gotchas

  • The npm cache can grow to 400+ MB for a full OpenClaw install. Make sure /data has enough free space before switching. On the Moto E2 with 4 GB internal, this requires careful space management alongside the rootfs
  • npm config set cache writes to ~/.npmrc. If you use both proot and native Termux, each environment has its own .npmrc — set the cache path in both
  • Running npm cache clean --force before the migration prevents carrying over any corrupted entries from the FAT32 era
  • If disk space is tight, you can periodically prune the cache with npm cache clean --force after installs are complete. The cache is only needed during npm install, not at runtime
  • On the native Termux setup (post proot), the /root/ path doesn't exist. Use $HOME/.npm-cache or $PREFIX/tmp/.npm-cache instead
  • The SD card is still useful for large file storage (logs, backups) — just not for npm's deeply nested cache structure

Result

MetricSD Card (FAT32)Rootfs (ext4)
Max path length255 chars (FAT32 limit)4096 chars (PATH_MAX)
Git dependenciesENAMETOOLONG failuresWorks reliably
Symlink supportNot supportedFull support
I/O speed~10-20 MB/s~50-100 MB/s
npm install reliabilityIntermittent failuresConsistent
Cache location/sdcard/npm-cache/root/.npm-cache