Skip to content
Latchkey

npm "EROFS: read-only file system" - Fix Writes to a Read-Only Path in CI

EROFS means npm attempted to write to a path mounted read-only - a cache dir, node_modules, or a global prefix on a read-only layer. The fix is to redirect npm’s writes to a writable location.

What this error means

npm fails with EROFS: read-only file system for a path under the cache, prefix, or install dir. It is common in hardened containers, distroless/read-only root filesystems, or when installing into a read-only mounted volume.

npm output
npm error code EROFS
npm error syscall mkdir
npm error path /nonexistent/.npm
npm error errno -30
npm error Error: EROFS: read-only file system, mkdir '/usr/lib/node_modules/...'

Diagnose it: what is different about the runner?

A build that passes locally and fails on a runner differs in a small number of predictable ways. Check those before changing build configuration, because the build config is usually not the thing that changed.

.github/workflows/ci.yml
- run: |
    node --version && npm --version
    echo "NODE_ENV=$NODE_ENV  CI=$CI"
    nproc && free -h && df -h /
    ls -la node_modules/.bin | head

Common causes

The npm cache or HOME points at a read-only path

A container with a read-only root filesystem leaves $HOME/~/.npm unwritable, so npm cannot create its cache directory.

Installing into a read-only mount

A global prefix or a project dir on a read-only volume cannot be written, so install or link operations hit EROFS.

How to fix it

Redirect npm writes to a writable dir

Set the cache and prefix to a writable, ephemeral location.

Terminal
export npm_config_cache=/tmp/.npm
export npm_config_prefix=/tmp/.npm-global
npm ci

Mount a writable working area

  1. Give the container a writable /tmp or a mounted volume for the workspace and cache.
  2. Ensure $HOME is writable, or override npm_config_cache.
  3. Install on a writable layer, not a read-only mount.

The three that account for most of them

  • Case sensitivity. Linux runners are case sensitive, macOS is not. An import with the wrong case resolves locally and fails in CI.
  • Out of memory. Exit code 137 is a SIGKILL from the kernel, not a build error. Raise --max-old-space-size or use a larger runner.
  • devDependencies pruned. NODE_ENV=production makes npm ci skip devDependencies, so the build tool itself goes missing. Set it after install, not before.

How to prevent it

  • Point npm cache/prefix at a writable path on read-only filesystems.
  • Install on writable layers, not read-only mounts.
  • Provide a writable HOME/tmp in hardened containers.

Frequently asked questions

What causes npm "EROFS: read-only file system"?
There are 2 common causes: the npm cache or home points at a read-only path and installing into a read-only mount. A container with a read-only root filesystem leaves $HOME/~/.npm unwritable, so npm cannot create its cache directory.
How do I fix npm "EROFS: read-only file system"?
There are 2 fixes depending on which cause you have: redirect npm writes to a writable dir and mount a writable working area. Work through them in order, since the first is the most common.
What does npm "EROFS: read-only file system" actually mean?
npm fails with EROFS: read-only file system for a path under the cache, prefix, or install dir.
How do I stop npm "EROFS: read-only file system" happening again?
Point npm cache/prefix at a writable path on read-only filesystems. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card