Skip to content

Conversation

@tennox
Copy link

@tennox tennox commented Dec 11, 2025

Summary

Fix chmod: Operation not permitted error when nix-direnv-reload file is owned by a
different user (e.g., a colleague entered direnv first).

$ direnv allow direnv: loading /etc/nixos/.envrc direnv: using flake . --impure --accept-flake-config chmod: changing permissions of '/etc/nixos/.direnv/bin/nix-direnv-reload': Operation not permitted

Problem

chmod cannot change permissions on a file owned by another user.

Solution

Use install -m 755 /dev/stdin instead of separate cat + chmod. The install command
unlinks and recreates the file rather than modifying it in place, which works even when the
existing file is owned by another user.

Test

Add this to .envrc:

source_url "https://raw.githubusercontent.com/tennox/nix-direnv/fix/chmod-permission-error/direnvrc" \ "sha256-rXKNtMDtfdKIeU3FnIDmEAyF5NZ3of+Yz2YuU8pYeJI="
…user Use `install -m 755` instead of separate cat + chmod to atomically create the file with correct permissions. This works even when an existing file is owned by another user (e.g., root), as install unlinks and recreates the file. Assisted-By: claude-opus-4-5-20251101 via Claude Code
@bbenne10
Copy link
Contributor

Has this fix been tested on Darwin? I worry about its options not matching a nixos or Linux provided binaries.

@tennox
Copy link
Author

tennox commented Dec 12, 2025

Has this fix been tested on Darwin? I worry about its options not matching a nixos or Linux provided binaries.

Good point. I ran some tests and found this to be a darwin-compatible version:

# Good (tested on Linux + macOS) install -m 755 /dev/stdin "$target" <<'EOF' ... EOF

Another option would be to just remove the file (did that for devenv) - but I wasn't sure if that would maybe reset other kinds of permissions. (But the file is created by "us" anyways, right? so we could just remove and recreate?)

tennox added a commit to tennox/devenv that referenced this pull request Dec 12, 2025
The previous pipe-based approach (printf | install /dev/stdin) doesn't work reliably on macOS. Use temp file + install instead, which: - Preserves exact contents of DEVENV_TASK_ENV (no shell expansion) - Fixes file-owned-by-another-user problem (install recreates) - Works on both Linux and macOS See: nix-community/nix-direnv#647 (comment) Assisted-By: claude-opus-4-5-20251101 via Claude Code
tennox added a commit to tennox/devenv that referenced this pull request Dec 12, 2025
The pipe-based `echo | install /dev/stdin` approach doesn't work reliably on macOS (piping to /dev/stdin fails on Darwin). Simply removing the file first achieves the same result: rm succeeds on files owned by other users (only needs directory write permission), then echo + chmod work on the newly created file we own. See: nix-community/nix-direnv#647 (comment) Assisted-By: claude-opus-4-5-20251101 via Claude Code
@bbenne10
Copy link
Contributor

Let's just do this the same way as you implemented it for devenv, please. Just rm the file if it exists before writing over it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants