Fixing 'chmod: invalid mode' when setting permissions on symlinks
Getting 'invalid mode' when trying to chmod a symlink? It's not a typo—chmod has specific rules for symlinks. Here's why and how to fix it.
When this error pops up
You're setting up a project directory, and you've got a symbolic link pointing to a config file. You run something like chmod 644 /path/to/link and get slapped with chmod: invalid mode: ‘/path/to/link’. Or maybe it says chmod: cannot access '/path/to/link': No such file or directory. It's not a typo — you typed the mode correctly. The problem is symlink.
I've seen this most often in CI/CD scripts or when someone's moving files around by hand and forgets that chmod has a mind of its own with symlinks. On Linux, if the symlink points to a file that doesn't exist yet (a dangling symlink), you'll get that error. Even if it does exist, you can't change symlink permissions directly using the normal syntax.
Root cause — chmod doesn't touch symlinks by default
Here's the deal: Linux permissions on symlinks don't actually matter. The kernel ignores them. When you run chmod on a symlink without special flags, it follows the link and changes the target file's permissions. If the target doesn't exist, you get the 'invalid mode' or 'cannot access' error because chmod is trying to resolve a path that isn't there.
But wait — even if you want to change the symlink's own permissions (for fun, or because some weird filesystem requires it), you can't do it with the default chmod command. You have to tell it explicitly.
The fix — use -h or --no-dereference
- Identify if it's a dangling symlink:
Runls -l /path/to/link. If the target path is highlighted in red or shows an arrow pointing to a nonexistent file, it's dangling. That's your problem. - Fix the target first (recommended):
If you want to change permissions on the target file, make sure the symlink points to a real file. Then run:
chmod 644 /path/to/link
This follows the link and changes the target. No error. - Change symlink permissions directly:
If you genuinely need to change the symlink's own permissions (rare, but some backup tools check them), use-h:
chmod -h 777 /path/to/dangling-link
This sets permissions on the symlink itself, regardless of the target's existence. - Alternative syntax:
On some systems (especially BSD/macOS),--no-dereferenceworks instead of-h:
chmod --no-dereference 777 /path/to/dangling-link - Batch fix multiple symlinks:
If you've got a ton of dangling symlinks and need to set them all to some permission, combine withfind:
find /path/to/dir -type l -exec chmod -h 777 {} \;
What to check if it still fails
- Filesystem type: Some filesystems (like FAT32, exFAT, or network filesystems) don't support symlinks at all, or they simulate them with special files.
chmod -hmay silently succeed but do nothing. Check withdf -T /path/to/link. - SELinux or AppArmor: Security modules can block
chmodon certain paths. If you get permission denied when using-h, checkausearch -m avc -ts recenton Red Hat/CentOS ordmesgfor AppArmor denials on Ubuntu. - Read-only filesystem: Obvious but sneaky. If the symlink is on a read-only mount, nothing works. Check
mount | grep /path. - Symbolic link loop: If the symlink points to another symlink that eventually points back to itself,
chmodmight hang or fail with 'too many levels of symbolic links'. Usereadlink -f /path/to/linkto resolve the full chain.
One last thing — don't rely on chmod -h to fix dangling symlinks in production scripts unless you're sure you want to change the link's own permissions (which are ignored by the kernel anyway). The real fix is usually ensuring the target exists. But now you know both roads.
Was this solution helpful?