How to Fix Linux Error EACCES (13): Permission Denied
Quick Fix Summary
TL;DRRun `ls -la` on the target file/directory, then use `chmod` or `chown` to correct the user/group permissions.
The EACCES (Error ACCESs) error, represented by errno 13, occurs when a process lacks the necessary filesystem permissions to perform an operation (read, write, or execute). It's a security enforcement mechanism, not a system failure, but it can halt critical services.
Diagnosis & Causes
Recovery Steps
Step 1: Diagnose the Permission Issue
First, identify the exact file/directory and the current user/context. Use `ls -la` and `id` to gather facts.
# Identify the problematic file/directory and current user
ls -la /path/to/target
id
ps aux | grep <your_process> Step 2: Fix Standard File Permissions (chmod/chown)
If standard Unix permissions are the issue, correct them using `chmod` to change modes or `chown` to change ownership. Be precise to avoid over-permissioning.
# Grant read/write to owner, read-only to group/others (common for configs)
sudo chmod 644 /path/to/file
# Change ownership to the service user (e.g., nginx, postgres)
sudo chown nginx:nginx /path/to/file
# Add execute permission for a script
sudo chmod +x /path/to/script.sh Step 3: Check and Fix Directory Traversal Permissions
To access a file, the user needs execute ('x') permission on every parent directory. Missing this is a common oversight.
# Check permissions on all parent directories
namei -l /path/to/deep/file
# Grant execute permission on a directory for user/group/others as needed
sudo chmod +x /path/to/parent/directory Step 4: Investigate Mandatory Access Control (SELinux/AppArmor)
If standard permissions look correct, a MAC system like SELinux (common on RHEL/CentOS/Fedora) is likely blocking access. Check and adjust the security context.
# Check for SELinux denials (tail audit log)
sudo tail -f /var/log/audit/audit.log | grep avc
# View file's SELinux context
ls -laZ /path/to/file
# Temporarily set permissive mode to test (Production: use `semanage fcontext` & `restorecon`)
sudo setenforce 0
# Restore default context after policy change
sudo restorecon -Rv /path/to/target Step 5: Verify Filesystem Mount Options
Filesystem mounts can have options like `noexec`, `nosuid`, or `ro` that override local permissions. Check `/etc/fstab` and the current mount table.
# Check mount options for the target filesystem
findmnt -T /path/to/target
grep /path/to/target /proc/mounts
# Review persistent mount settings
cat /etc/fstab | grep <relevant_mount_point> Step 6: Resolve Sticky Bit or Special Permission Issues
Special permissions like the sticky bit on directories (e.g., /tmp) or setuid/setgid bits can cause unexpected EACCES for non-owners.
# Identify special permissions (look for 't', 's', 'S' in ls -la output)
ls -la /directory
# Example: Remove setgid bit if causing issues
sudo chmod g-s /path/to/directory Architect's Pro Tip
"For containerized apps (Docker/K8s), EACCES often stems from mismatched UIDs/GIDs between the host volume and container user. Use `stat` to compare and set `podman run --user` or securityContext in Kubernetes."
Frequently Asked Questions
I fixed permissions with chmod 777, but it still doesn't work. Why?
This strongly points to SELinux/AppArmor (Step 4) or filesystem mount options like `noexec` (Step 5). Never use `chmod 777` in production; it's a major security anti-pattern.
How do I differentiate EACCES from ENOENT (No such file or directory)?
ENOENT (errno 2) means the path doesn't exist. EACCES (errno 13) means the path exists, but access is denied. Check your error logs or use `strace` on the failing process for the exact errno.
My script runs manually but fails via cron/crontab. Is this EACCES?
Yes, likely. Cron jobs run with a minimal environment and a different user (often root or the crontab owner). Ensure the script and all files/directories it accesses have correct permissions for the cron user, and that environment variables (like PATH) are fully set within the script.