This Node.js error occurs when the operating system blocks a file system operation due to insufficient permissions, file locking by another process, or security restrictions. Common scenarios include writing to protected directories, accessing files opened by other applications, or operating on files locked by antivirus software.
The SystemError "access denied" indicates that Node.js attempted a file system operation (read, write, delete, or modify) but the operating system rejected it. Unlike the more specific EACCES or EPERM error codes, this generic SystemError message means the OS blocked the operation at a lower level, often due to file locking, security policies, or process-level restrictions. This error is distinct from permission errors like EACCES because it represents a broader class of OS-level rejections. The operation might have been rejected by Windows file locking mechanisms, antivirus real-time protection, security software, or even filesystem driver restrictions. The error typically includes the system call that failed (like "open", "unlink", or "rename") and the path involved. On Windows systems, this error frequently occurs due to exclusive file locks that prevent Node.js from accessing files currently open in other applications. On Linux and macOS, it may indicate SELinux policies, AppArmor restrictions, or mandatory access control systems blocking the operation beyond standard Unix permissions.
First, verify whether another application has the file open:
Windows:
# Use Resource Monitor to find processes using the file
# Press Win+R, type "resmon", go to CPU tab, search for filename in "Associated Handles"
# Or use PowerShell:
$file = "C:\path\to\file.txt"
Get-Process | ForEach-Object { $_.Modules } | Where-Object { $_.FileName -eq $file }Linux/macOS:
# List processes using the file
lsof /path/to/file.txt
# Or find which process is accessing a directory
lsof +D /path/to/directoryClose any applications that have the file open, or add retry logic to your Node.js code to handle temporary locks.
Check that your Node.js process has the necessary permissions:
Windows:
# View file permissions
icacls "C:\path\to\file.txt"
# Grant full control to current user
icacls "C:\path\to\file.txt" /grant "%USERNAME%":FLinux/macOS:
# Check file permissions
ls -la /path/to/file.txt
# Check directory permissions (need write permission on directory to create/delete files)
ls -ld /path/to/directory
# Fix permissions if needed
sudo chown $USER:$USER /path/to/file.txt
chmod 644 /path/to/file.txt # rw-r--r--
chmod 755 /path/to/directory # rwxr-xr-xEnsure the user running your Node.js process has read/write access to both the file and its parent directory.
Antivirus software often locks files during real-time scanning:
Test if antivirus is the cause:
1. Temporarily disable real-time protection (Windows Defender, Norton, McAfee, etc.)
2. Run your Node.js script again
3. If it succeeds, the antivirus is interfering
Permanent fix - add exclusions:
Windows Defender:
# Add folder exclusion
Add-MpPreference -ExclusionPath "C:\path\to\project"
# Or via GUI: Windows Security → Virus & threat protection → Manage settings → Add exclusionsImportant: Only exclude directories you trust. Consider excluding:
- Your project's node_modules directory
- Build output directories (dist, build)
- Temporary directories used by your application
Never exclude system-wide directories or disable antivirus permanently.
Add automatic retry with exponential backoff for operations that may encounter temporary locks:
const fs = require('fs').promises;
async function writeFileWithRetry(path, data, maxRetries = 5) {
for (let i = 0; i < maxRetries; i++) {
try {
await fs.writeFile(path, data);
return; // Success
} catch (error) {
if (error.message?.includes('access denied') ||
error.message?.includes('operation was rejected')) {
if (i === maxRetries - 1) throw error; // Last attempt failed
// Exponential backoff: 100ms, 200ms, 400ms, 800ms, 1600ms
const delay = 100 * Math.pow(2, i);
console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error; // Not a locking error, fail immediately
}
}
}
}
// Usage
try {
await writeFileWithRetry('./output.txt', 'data');
console.log('File written successfully');
} catch (error) {
console.error('Failed after retries:', error.message);
}This approach handles transient locks from antivirus, backup software, or brief file access by other processes.
If accessing protected system directories is required, run with administrator/root privileges:
Windows (Run as Administrator):
# Right-click Command Prompt or PowerShell, select "Run as administrator"
# Then run your Node.js script
node your-script.js
# Or use runas command
runas /user:Administrator "node your-script.js"Linux/macOS:
# Run with sudo (use cautiously)
sudo node your-script.js
# Better: Fix ownership instead of using sudo
sudo chown -R $USER:$USER /path/to/directoryImportant security note: Avoid running Node.js applications as administrator/root unless absolutely necessary. If you must access protected directories:
1. Create a dedicated service account with minimal required permissions
2. Grant specific permissions to that account
3. Run your Node.js process under that account
4. Never run web-facing Node.js servers as root/administrator
Verify the file or filesystem isn't protected by read-only settings:
Windows:
# Check if file is read-only
attrib "C:\path\to\file.txt"
# Remove read-only attribute
attrib -R "C:\path\to\file.txt"
# Check if disk is mounted read-only (rare on Windows)
mountvolLinux/macOS:
# Check filesystem mount status
mount | grep /path/to/filesystem
# If mounted read-only, remount as read-write (requires root)
sudo mount -o remount,rw /path/to/filesystem
# Check for immutable flag
lsattr /path/to/file.txt
# Remove immutable flag if set (requires root)
sudo chattr -i /path/to/file.txtFor network shares (SMB/NFS), check share permissions on the server side.
Platform-Specific Considerations:
On Windows, the most common cause is file locking due to the way Windows handles concurrent file access. Unlike Unix systems that allow multiple processes to read a file while one writes, Windows often uses exclusive locks. The fs.openSync() function calls CreateFile with shared read/write flags, but other applications may not, leading to conflicts.
SELinux and AppArmor on Linux:
If running on a Linux system with SELinux (Red Hat, CentOS, Fedora) or AppArmor (Ubuntu, Debian), check security contexts:
# SELinux: Check context
ls -Z /path/to/file.txt
# View denials
sudo ausearch -m AVC -ts recent
# Temporarily set to permissive mode (for testing only)
sudo setenforce 0
# AppArmor: Check status
sudo aa-status
# View denials
sudo dmesg | grep apparmorFile Locking Libraries:
For production applications that need robust file locking across platforms, consider using dedicated libraries instead of relying on OS-level locks:
- proper-lockfile: Cross-platform lockfile implementation using atomic operations
- lockfile: Simple lockfile creation with stale lock detection
- os-lock: Cross-platform file locking using native OS mechanisms
Docker and Container Environments:
In containerized environments, ensure:
1. Volumes are mounted with correct permissions
2. The container user has necessary UIDs/GIDs
3. No SELinux or AppArmor policies block container file access
4. Host antivirus isn't scanning mounted volumes in real-time
Windows-Specific: User Account Control (UAC):
Operations on protected locations (Program Files, Windows directory) trigger UAC even with admin accounts. Either:
1. Store application data in user directories (%APPDATA%, %LOCALAPPDATA%)
2. Request elevation via manifest file in packaged applications
3. Use Windows Services with appropriate service account permissions
Debugging Techniques:
Enable detailed error logging in Node.js:
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', {
message: error.message,
code: error.code,
syscall: error.syscall,
path: error.path,
errno: error.errno,
stack: error.stack
});
});Use process monitoring tools:
- Windows: Process Monitor (Procmon) from Sysinternals to trace file operations
- Linux: strace node script.js to see system calls and their return codes
- macOS: dtruss -n node script.js (requires SIP modifications)
Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams