How to fix Error: EROFS: read-only file system, write in Node.js
This error occurs when a Node.js application attempts to write to a file or directory on a read-only filesystem. Common in containerized environments, serverless platforms, and systems with intentionally read-only root filesystems.
Quick fix
Fixes EROFS
Error: EROFS: read-only file system, write
at Object.writeFileSync (node:fs:2129:3)
at /app/src/cache.js:45:8- Identify which write operation is failing
- Use /tmp directory for temporary writes
- Configure writable volumes in Docker
- Move caching to environment variables or external storage
Error: EROFS: read-only file system, writeat Object.writeFileSync (node:fs:2129:3)at /app/src/cache.js:45:8Error: EROFS: read-only file system, write
What this error means
The EROFS error (Error Read-Only File System) indicates that Node.js attempted to perform a write operation on a filesystem that is mounted as read-only. This is a system-level restriction where the operating system prevents any modifications to the filesystem. This error is increasingly common in modern deployment environments. Docker containers often run with read-only root filesystems as a security best practice. Serverless platforms like Vercel, AWS Lambda, and Netlify Functions mount the application code as read-only, allowing writes only to specific temporary directories. Additionally, embedded systems and IoT devices may use read-only filesystems to prevent corruption. The error occurs when your Node.js code attempts operations like fs.writeFile(), fs.mkdir(), or when npm tries to create symlinks or cache directories during runtime. The underlying filesystem simply refuses these write operations, causing Node.js to throw this error.
Typical symptoms
- Application crashes when trying to write files or create directories
- npm commands fail with "EROFS: read-only file system, mkdir" errors
- File caching operations fail during application runtime
- Build or deployment scripts fail with filesystem write errors
- Container startup fails with permission-related EROFS errors
- Temporary file creation operations throw read-only filesystem errors
Common causes
- Docker container running with --read-only flag or readOnlyRootFilesystem: true in Kubernetes
- Serverless function attempting to write outside the /tmp directory
- Application code trying to write to the application root directory in production
- npm or package manager attempting to create symlinks or cache during runtime
- Filesystem mounted as read-only due to disk errors or emergency mode
- Embedded system or IoT device with intentionally read-only root filesystem
- Build cache or temporary files being written to non-writable locations
How to fix "Error: EROFS: read-only file system, write"
Check your error stack trace to determine exactly where the write is being attempted:
Error: EROFS: read-only file system, write
at Object.writeFileSync (node:fs:2129:3)
at /app/src/cache.js:45:8Look for operations like:
- fs.writeFile(), fs.writeFileSync()
- fs.mkdir(), fs.mkdirSync()
- fs.appendFile()
- Package manager operations (npm, yarn)
Change your code to write to the /tmp directory, which is writable in most environments:
const fs = require('fs');
const path = require('path');
// ❌ Don't write to application directory
// fs.writeFileSync('./cache/data.json', data);
// ✅ Write to /tmp instead
const tmpPath = path.join('/tmp', 'data.json');
fs.writeFileSync(tmpPath, data);In serverless environments like AWS Lambda or Vercel, /tmp is the only writable location and has storage limits (512MB in Lambda).
If running in Docker, mount tmpfs volumes for directories that need to be writable:
# docker-compose.yml
services:
app:
image: node:20
read_only: true
tmpfs:
- /tmp
- /app/.npm
- /app/node_modules/.cacheOr in Kubernetes:
apiVersion: v1
kind: Pod
spec:
containers:
- name: app
image: node:20
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /app/.cache
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}For persistent data, use external storage instead of filesystem writes:
// Instead of file-based caching:
// fs.writeFileSync('./cache.json', JSON.stringify(data));
// Use Redis, DynamoDB, or environment variables:
const redis = require('redis');
const client = redis.createClient();
await client.set('cache-key', JSON.stringify(data));For configuration, use environment variables:
// Instead of writing config files:
// fs.writeFileSync('./config.json', config);
// Read from environment:
const config = {
apiKey: process.env.API_KEY,
endpoint: process.env.API_ENDPOINT
};If npm or yarn is causing EROFS errors during runtime, configure cache to use /tmp:
# Set npm cache location
npm config set cache /tmp/.npm
# Or use environment variable
export npm_config_cache=/tmp/.npmIn your Dockerfile:
ENV npm_config_cache=/tmp/.npm
ENV NODE_OPTIONS="--max-old-space-size=4096"
# Install dependencies at build time, not runtime
RUN npm ci --only=productionIf you have root access and the read-only state is unintentional (disk errors, emergency mode), remount as read-write:
# Check current mount status
mount | grep "on / "
# Remount root filesystem as read-write
sudo mount -o remount,rw /
# Or for specific mount point
sudo mount -o remount,rw /data⚠️ Warning: Only do this on systems you control. In containerized/serverless environments, read-only filesystems are intentional security measures.
Advanced notes
Serverless Platform Specifics:
- AWS Lambda: /tmp has 512MB limit and persists only for the lifetime of the execution environment
- Vercel: Only /tmp is writable; all other paths are read-only
- Netlify Functions: Similar to AWS Lambda, use /tmp for temporary storage
- Google Cloud Functions: /tmp is mounted as tmpfs with instance memory limit
Security Benefits of Read-Only Filesystems:
Read-only root filesystems prevent attackers from modifying application code or installing malware if they gain access. This is why Kubernetes security policies often require readOnlyRootFilesystem: true. Design your applications to be stateless and write to external storage instead.
Detecting Filesystem Status in Code:
const fs = require('fs');
const path = require('path');
function isWritable(directory) {
const testFile = path.join(directory, '.write-test');
try {
fs.writeFileSync(testFile, 'test');
fs.unlinkSync(testFile);
return true;
} catch (error) {
return false;
}
}
console.log('/ writable:', isWritable('/'));
console.log('/tmp writable:', isWritable('/tmp'));Build vs Runtime Considerations:
Distinguish between build-time and runtime writes. During Docker image builds, the filesystem is writable, so npm install works. At runtime with read-only containers, any post-build file writes will fail. Ensure all dependencies are installed during the build phase.
Frequently asked questions
- What does "EROFS" mean?
- js attempted to perform a write operation on a filesystem that is mounted as read-only. This is a system-level restriction where the operating system prevents any modifications to the filesystem. This error is increasingly common in modern deployment environments.
- How do I fix "EROFS"?
- This error occurs when a Node.js application attempts to write to a file or directory on a read-only filesystem. Common in containerized environments, serverless platforms, and systems with intentionally read-only root filesystems.
- What causes "EROFS"?
- Docker container running with --read-only flag or readOnlyRootFilesystem: true in Kubernetes Serverless function attempting to write outside the /tmp directory Application code trying to write to the application root directory in production
- Is the "EROFS" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚Node.js Official Documentation
- 📖Node.js Common System Errors Documentation(Official Docs)
- 📖Node.js File System API Documentation(Official Docs)
- 🐙
- 🐙