The "Operation not permitted" error when creating symbolic links for Neovim on macOS is caused by System Integrity Protection (SIP) restricting access to system directories like /usr/local or /Applications. To resolve this, you must either grant Full Disk Access to your terminal emulator in Privacy settings or configure Neovim to store its configuration in the user-specific ~/.config/nvim directory instead of a system-wide location.
Understanding the Root Cause
macOS includes a security feature called System Integrity Protection (SIP), often referred to as "rootless." This mechanism prevents even the root user from modifying certain protected areas of the filesystem, including/System, /usr, and /bin. When you attempt to create a symbolic link using ln -s pointing to or from these restricted paths, the operating system blocks the operation with an "Operation not permitted" error.
This issue frequently arises when users try to symlink their Neovim configuration files into standard system locations or when they use package managers that attempt to write to protected directories. Unlike Linux, where such operations are common, macOS enforces stricter boundaries to maintain system stability and security. Therefore, understanding where SIP applies is crucial for troubleshooting development environment issues on Apple Silicon and Intel Macs alike.
Solution 1: Use User-Specific Configuration Paths
The most robust and recommended solution is to avoid symlinking into protected system directories altogether. Neovim is designed to look for configuration files in specific user-level directories by default. By adhering to these standards, you bypass SIP restrictions entirely without needing to adjust system security settings. Neovim searches for its configuration in the following order:$XDG_CONFIG_HOME/nvim~/.config/nvim~/.nvim~/.vimrc
~/.config/nvim to your repository's nvim folder. For example, if your config is stored in ~/dotfiles/nvim, you would run:
mkdir -p ~/.config
ln -s ~/dotfiles/nvim ~/.config/nvim
Since both the source (~/dotfiles) and destination (~/.config) reside within your user space, macOS allows this operation without triggering SIP protections. This approach also ensures that your Neovim configuration is portable across different machines and does not interfere with system updates.
Solution 2: Grant Full Disk Access to Your Terminal
If you have a specific requirement to symlink into a protected directory, you may need to grant your terminal application Full Disk Access. This permission overrides SIP restrictions for that specific application, allowing it to read and write to any part of the filesystem. Navigate to System Settings > Privacy & Security > Full Disk Access. Click the plus icon (+) and locate your terminal application, such asTerminal.app, iTerm2, or kitty. Once added, restart your terminal session to apply the changes.
Be aware that granting Full Disk Access increases the attack surface of your system. While convenient for development, it is generally safer to keep SIP enabled and use user-space directories whenever possible. Additionally, note that some third-party terminals may require explicit authorization after macOS updates, so re-check this setting periodically.
Verifying Your Setup
After applying one of the solutions above, verify that the symbolic link works correctly. You can check the link status using thels -l command:
ls -l ~/.config/nvim
The output should show a path starting with -> indicating the target directory. If the link is broken or permissions are incorrect, Neovim will fail to load your configuration. Ensure that your Git repository has been pulled recently so that the latest configuration changes are reflected in the symlinked directory.
For more information on managing local repositories on macOS, you might find Moving Local Git Repo from M1 Mac Mini to External Hard Drive useful, especially if your dotfiles are stored on external media. Similarly, Moving Local Git Repo from M1 Mac Mini to External APFS Hard Drive provides insights into handling case-sensitive file systems which can sometimes cause subtle issues with symlink resolution.
Frequently Asked Questions
Why does ln -s work in Linux but fail on macOS?
Linux distributions typically do not enforce System Integrity Protection by default, allowing root or sudo users to modify almost any part of the filesystem. macOS restricts these operations to protect core system files from accidental or malicious modification, resulting in the "Operation not permitted" error when SIP is active.Can I disable SIP entirely to fix this error?
Disabling SIP is technically possible by booting into Recovery Mode and runningcsrutil disable in the Terminal. However, this is strongly discouraged because it removes critical security protections, leaving your system vulnerable to malware and system instability. It is much safer to use user-space directories or grant specific app permissions instead.
What if I am using Homebrew to install Neovim?
Homebrew installs software in/opt/homebrew on Apple Silicon and /usr/local on Intel Macs. These locations are generally accessible to users, but symlinking *into* them from system directories may still be blocked. Always ensure your source and destination paths are within your user home directory to avoid permission conflicts regardless of how Neovim was installed.
How do I check if my terminal has Full Disk Access?
Open System Settings, go to Privacy & Security, and select Full Disk Access. Look for your terminal application in the list. If the toggle switch next to it is off, click it to enable access. You must quit and relaunch the terminal application for the new permissions to take effect.Does this error affect other text editors like Vim or VS Code?
Yes, any application attempting to create symbolic links in protected directories will encounter similar errors. The solution remains the same: move configuration files to user-space directories like~/.config or ~/.local. Editors like VS Code can manage their own settings in user directories without requiring symlinks to system paths.