Permission Denied β How to Fix It (Linux, Mac, Windows)
bash: ./script.sh: Permission denied
PermissionError: [Errno 13] Permission denied
EACCES: permission denied, open '/usr/local/lib/node_modules'
βPermission deniedβ means your current user account doesnβt have the required access level (read, write, or execute) for the file, directory, or operation youβre attempting.
How Linux/Mac permissions work
Every file and directory has three permission sets:
- Owner β the user who created it
- Group β users in the fileβs group
- Others β everyone else
Each set has three permissions:
- r (read) β view file contents or list directory
- w (write) β modify file or create/delete files in directory
- x (execute) β run as program or enter directory
# Example: ls -la output
-rwxr-xr-- 1 alice developers 4096 May 15 script.sh
ββββ€βββ€βββ€
β β β βββ Others: read only
β β βββββββ Group: read + execute
β βββββββββββ Owner: read + write + execute
βββββββββββββ File type (- = file, d = directory)
Fix 1: Make a script executable
The most common case β you created a script but forgot to add execute permission.
# β Script isn't executable
./deploy.sh # Permission denied
# β
Add execute permission for the owner
chmod +x deploy.sh
./deploy.sh # Works
# Or be specific about who gets execute
chmod u+x deploy.sh # Only owner
chmod a+x deploy.sh # Everyone
Why this happens: When you create a file (with a text editor, touch, or download), it doesnβt get execute permission by default. This is a security feature β you must explicitly mark files as executable.
Fix 2: Fix file ownership
If a file is owned by root or another user, you canβt modify it even if the permissions look right.
# Check ownership
ls -la config.yml
# -rw-r--r-- 1 root root 256 May 15 config.yml
# ^^^^ owned by root!
# Change ownership to your user
sudo chown $USER:$USER config.yml
# Recursively for a directory
sudo chown -R $USER:$USER ./my-project/
# Change only the group
sudo chgrp developers shared-folder/
Common cause: Running a command with sudo creates files owned by root. Then your normal user canβt modify them. Avoid sudo unless necessary.
Fix 3: Use sudo correctly
Some operations legitimately require root access β writing to system directories, installing system packages, modifying system config.
# β Direct write to system directory
echo "127.0.0.1 myapp.local" > /etc/hosts # Permission denied
# β
Use sudo with tee (preserves redirect)
echo "127.0.0.1 myapp.local" | sudo tee -a /etc/hosts
# β Don't do this β creates root-owned files in your project
sudo npm install
sudo pip install
# β
Fix the underlying permission issue instead
Rule: If you need sudo for development tools (npm, pip, docker), the tool is misconfigured. Fix the configuration rather than using sudo as a workaround.
Fix 4: SSH key permissions
SSH is strict about key file permissions. If your private key is readable by others, SSH refuses to use it.
# β Key permissions too open
ssh user@server
# Permissions 0644 for '/home/user/.ssh/id_rsa' are too open.
# It is required that your private key files are NOT accessible by others.
# β
Fix SSH directory and key permissions
chmod 700 ~/.ssh # Directory: owner only
chmod 600 ~/.ssh/id_rsa # Private key: owner read/write only
chmod 644 ~/.ssh/id_rsa.pub # Public key: owner read/write, others read
chmod 644 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/known_hosts
chmod 600 ~/.ssh/config # SSH config: owner only
Fix 5: npm/Node.js EACCES errors
# β Global install fails
npm install -g typescript
# EACCES: permission denied, mkdir '/usr/local/lib/node_modules/typescript'
Donβt use sudo npm install -g β it creates root-owned files that cause more problems later.
Option A: Change npmβs default directory:
mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc # or ~/.zshrc
source ~/.bashrc
npm install -g typescript # Works without sudo
Option B: Use nvm (recommended):
# nvm installs Node in your home directory β no permission issues
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
nvm install --lts
npm install -g typescript # Works without sudo
Fix 6: Docker permission denied
# β Can't run docker commands
docker ps
# permission denied while trying to connect to the Docker daemon socket
# β
Add your user to the docker group
sudo usermod -aG docker $USER
# IMPORTANT: Log out and back in (or restart) for the group change to take effect
# Verify:
groups # Should show 'docker' in the list
On macOS: Docker Desktop handles permissions automatically. If you get permission errors, restart Docker Desktop.
Fix 7: Python PermissionError
# β Writing to a directory you don't own
with open('/var/log/myapp.log', 'w') as f: # PermissionError
# β
Write to a user-accessible location
with open(os.path.expanduser('~/myapp.log'), 'w') as f:
# β
Or create the directory with proper permissions first
os.makedirs('/var/log/myapp', exist_ok=True) # Needs sudo once
For pip install errors:
# β System Python is protected
pip install requests # Permission denied
# β
Use a virtual environment
python -m venv .venv
source .venv/bin/activate
pip install requests # Works β installs in .venv/
Fix 8: Git permission denied
# β Can't push to remote
git push origin main
# Permission denied (publickey)
# Check if your SSH key is loaded
ssh-add -l
# If empty, add your key
ssh-add ~/.ssh/id_rsa
# Test the connection
ssh -T git@github.com
See Git Permission Denied Publickey β Fix for a complete guide.
Permission numbers cheat sheet
| Number | Permission | Meaning |
|---|---|---|
| 7 | rwx | Read + Write + Execute |
| 6 | rw- | Read + Write |
| 5 | r-x | Read + Execute |
| 4 | rβ | Read only |
| 0 | --- | No access |
Common combinations:
chmod 755 directory/ # Owner: full, Others: read+execute (standard for directories)
chmod 644 file.txt # Owner: read+write, Others: read (standard for files)
chmod 600 secret.key # Owner only (private keys, credentials)
chmod 777 file # β NEVER do this β everyone can read/write/execute
FAQ
Should I use chmod 777 to fix permission errors?
No. chmod 777 gives everyone full access, which is a security risk. Itβs the equivalent of leaving your front door open. Find the specific permission needed and grant only that.
Why do I get βOperation not permittedβ instead of βPermission deniedβ?
βOperation not permittedβ (EPERM) means even root canβt do it β the operation is blocked by the system (e.g., modifying immutable files, SIP on macOS, or SELinux). βPermission deniedβ (EACCES) means your user lacks the required permission but root could do it.
How do I fix permissions on macOS with SIP?
System Integrity Protection prevents modifying /usr/bin, /System, and other protected paths β even with sudo. You canβt disable it without booting into Recovery Mode. Instead, install tools to /usr/local/bin (Homebrew does this automatically).
Whatβs the difference between chmod and chown?
chmod changes what actions are allowed (read/write/execute). chown changes who owns the file. You might need both: chown to make yourself the owner, then chmod to set the right permissions.