Incus profile edit looks for EDITOR but doesn't have users PATH available?

incus profile edit incus-os:metasyn
Error: exec: “nvim”: executable file not found in $PATH

where, I can confirm it is on my user’s PATH. Changing it to EDITOR=vi or something works, but, I was surprised as I’m not running sudo incus?

incus --version

returns 6.21

It should be able to find it, Go will go through each entry of your PATH env variable and look for the binary in there. What wouldn’t work is if nvim is some kind of shell alias for example.

I’m not sure what the issue is:

❯ file $(which nvim)
/home/xander/.local/share/mise/installs/neovim/0.11.5/nvim-linux-x86_64/bin/nvim: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d167752c8e7deda0cdb1af59df69289a5f72c7e5, for GNU/Linux 3.2.0, with debug_info, not stripped
```

Its just a normal binary

Maybe run the command under strace -f? You should see stat calls or similar for all the possible paths that Go is trying.

Good idea:

strace -f incus profile edit default 2>&1 | grep -v sleep | grep -v clock

gives

[pid 307908] newfstatat(AT_FDCWD, "/tmp/editor_55333913.yaml",  <unfinished ...>
[pid 307908] <... newfstatat resumed>0x3a002b107a38, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)
[pid 307908] renameat(AT_FDCWD, "/tmp/editor_55333913", AT_FDCWD, "/tmp/editor_55333913.yaml" <unfinished ...>
[pid 307908] <... renameat resumed>)    = 0
[pid 307908] newfstatat(AT_FDCWD, "/opt/incus/bin/nvim",  <unfinished ...>
[pid 307908] <... newfstatat resumed>0x3a002b107b08, 0) = -1 ENOENT (No such file or directory)
[pid 307908] newfstatat(AT_FDCWD, "/bin/nvim", 0x3a002b107bd8, 0) = -1 ENOENT (No such file or directory)
[pid 307908] newfstatat(AT_FDCWD, "/usr/bin/nvim",  <unfinished ...>
[pid 307908] <... newfstatat resumed>0x3a002b107ca8, 0) = -1 ENOENT (No such file or directory)
[pid 307908] newfstatat(AT_FDCWD, "/sbin/nvim",  <unfinished ...>
[pid 307908] <... newfstatat resumed>0x3a002b107d78, 0) = -1 ENOENT (No such file or directory)
[pid 307908] newfstatat(AT_FDCWD, "/usr/sbin/nvim",  <unfinished ...>
[pid 307908] <... newfstatat resumed>0x3a002b107e48, 0) = -1 ENOENT (No such file or directory)
[pid 307908] newfstatat(AT_FDCWD, "/usr/local/bin/nvim", 0x3a002b3ca038, 0) = -1 ENOENT (No such file or directory)
[pid 307908] newfstatat(AT_FDCWD, "/usr/local/sbin/nvim",  <unfinished ...>
[pid 307908] <... newfstatat resumed>0x3a002b3ca108, 0) = -1 ENOENT (No such file or directory)
[pid 307908] unlinkat(AT_FDCWD, "/tmp/editor_55333913.yaml", 0 <unfinished ...>
[pid 307908] <... unlinkat resumed>)    = 0
[pid 307908] write(2, "Error: exec: \"nvim\": executable "..., 56Error: exec: "nvim": executable file not found in $PATH
) = 56
[pid 307908] exit_group(1 <unfinished ...>

It seems to have skipped over the various things in local.

So, maybe if I try setting the path to explicitly exclude it:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin strace -f incus profile edit default 2>&1 | grep -v sleep | grep -v clock
[pid 309230] write(3, "### This is a YAML representatio"..., 655) = 655
[pid 309230] close(3 <unfinished ...>
[pid 309230] <... close resumed>)       = 0
[pid 309230] newfstatat(AT_FDCWD, "/tmp/editor_753352514.yaml",  <unfinished ...>
[pid 309230] <... newfstatat resumed>0x548b0f8ae08, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)
[pid 309230] renameat(AT_FDCWD, "/tmp/editor_753352514", AT_FDCWD, "/tmp/editor_753352514.yaml" <unfinished ...>
[pid 309230] <... renameat resumed>)    = 0
[pid 309230] newfstatat(AT_FDCWD, "/opt/incus/bin/nvim",  <unfinished ...>
[pid 309230] <... newfstatat resumed>0x548b0f8aed8, 0) = -1 ENOENT (No such file or directory)
[pid 309230] newfstatat(AT_FDCWD, "/bin/nvim",  <unfinished ...>
[pid 309230] <... newfstatat resumed>0x548b0f8afa8, 0) = -1 ENOENT (No such file or directory)
[pid 309230] newfstatat(AT_FDCWD, "/usr/bin/nvim",  <unfinished ...>
[pid 309230] <... newfstatat resumed>0x548b0f8b078, 0) = -1 ENOENT (No such file or directory)
[pid 309230] newfstatat(AT_FDCWD, "/sbin/nvim", 0x548b0f8b148, 0) = -1 ENOENT (No such file or directory)
[pid 309230] newfstatat(AT_FDCWD, "/usr/sbin/nvim",  <unfinished ...>
[pid 309230] <... newfstatat resumed>0x548b0f8b218, 0) = -1 ENOENT (No such file or directory)
[pid 309230] newfstatat(AT_FDCWD, "/usr/local/bin/nvim",  <unfinished ...>
[pid 309230] <... newfstatat resumed>0x548b0f8b2e8, 0) = -1 ENOENT (No such file or directory)
[pid 309230] newfstatat(AT_FDCWD, "/usr/local/sbin/nvim",  <unfinished ...>
[pid 309230] <... newfstatat resumed>0x548b0f8b3b8, 0) = -1 ENOENT (No such file or directory)
[pid 309230] unlinkat(AT_FDCWD, "/tmp/editor_753352514.yaml", 0 <unfinished ...>
[pid 309230] <... unlinkat resumed>)    = 0
[pid 309230] write(2, "Error: exec: \"nvim\": executable "..., 56 <unfinished ...>

or if I explicitly include it:

❯ which nvim
/home/xander/.local/share/mise/installs/neovim/0.11.5/nvim-linux-x86_64/bin/nvim

then put it on path:

PATH=/home/xander/.local/share/mise/installs/neovim/0.11.5/nvim-linux-x86_64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin strace -f incus profile edit default 2>&1 | grep -v sleep | grep -v clock
[pid 309488] write(3, "### This is a YAML representatio"..., 655) = 655
[pid 309488] close(3 <unfinished ...>
[pid 309488] <... close resumed>)       = 0
[pid 309488] newfstatat(AT_FDCWD, "/tmp/editor_3118423206.yaml",  <unfinished ...>
[pid 309488] <... newfstatat resumed>0x24df554aa1d8, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)
[pid 309488] renameat(AT_FDCWD, "/tmp/editor_3118423206", AT_FDCWD, "/tmp/editor_3118423206.yaml" <unfinished ...>
[pid 309488] <... renameat resumed>)    = 0
[pid 309488] newfstatat(AT_FDCWD, "/opt/incus/bin/nvim",  <unfinished ...>
[pid 309488] <... newfstatat resumed>0x24df554aa2a8, 0) = -1 ENOENT (No such file or directory)
[pid 309488] newfstatat(AT_FDCWD, "/bin/nvim",  <unfinished ...>
[pid 309488] <... newfstatat resumed>0x24df554aa378, 0) = -1 ENOENT (No such file or directory)
[pid 309488] newfstatat(AT_FDCWD, "/usr/bin/nvim",  <unfinished ...>
[pid 309488] <... newfstatat resumed>0x24df554aa448, 0) = -1 ENOENT (No such file or directory)
[pid 309488] newfstatat(AT_FDCWD, "/sbin/nvim", 0x24df554aa518, 0) = -1 ENOENT (No such file or directory)
[pid 309488] newfstatat(AT_FDCWD, "/usr/sbin/nvim",  <unfinished ...>
[pid 309488] <... newfstatat resumed>0x24df554aa5e8, 0) = -1 ENOENT (No such file or directory)
[pid 309488] newfstatat(AT_FDCWD, "/usr/local/bin/nvim", 0x24df554aa6b8, 0) = -1 ENOENT (No such file or directory)
[pid 309488] newfstatat(AT_FDCWD, "/usr/local/sbin/nvim",  <unfinished ...>
[pid 309488] <... newfstatat resumed>0x24df554aa788, 0) = -1 ENOENT (No such file or directory)
[pid 309488] unlinkat(AT_FDCWD, "/tmp/editor_3118423206.yaml", 0 <unfinished ...>
[pid 309488] <... unlinkat resumed>)    = 0
[pid 309488] write(2, "Error: exec: \"nvim\": executable "..., 56Error: exec: "nvim": executable file not found in $PATH
 <unfinished ...>

:thinking:

I think it must have something to do with my usage of https://mise.jdx.dev/

❯ env -i bash --noprofile --norc
bash-5.2$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
bash-5.2$ export PATH=$PATH:/home/xander/.local/share/mise/installs/neovim/0.11.6/bin
bash-5.2$ nvim --version
NVIM v0.11.6
Build type: Release
LuaJIT 2.1.1741730670
Run "nvim -V1 -v" for more info
bash-5.2$ which nvim
/home/xander/.local/share/mise/installs/neovim/0.11.6/bin/nvim
bash-5.2$ export EDITOR=nvim

then

strace -f incus profile edit default 2>&1 | grep -v sleep | grep -v clock

gives us:

[pid 316864] write(6, "### This is a YAML representatio"..., 655 <unfinished ...>
[pid 316863] sched_yield( <unfinished ...>
[pid 316864] <... write resumed>)       = 655
[pid 316864] close(6 <unfinished ...>
[pid 316863] <... sched_yield resumed>) = 0
[pid 316857] futex(0x2a70ac74d160, FUTEX_WAIT_PRIVATE, 0, NULL <unfinished ...>
[pid 316864] <... close resumed>)       = 0
[pid 316863] futex(0x2a70ac780960, FUTEX_WAIT_PRIVATE, 0, NULL <unfinished ...>
[pid 316864] newfstatat(AT_FDCWD, "/tmp/editor_4133246938.yaml",  <unfinished ...>
[pid 316864] <... newfstatat resumed>0x2a70ac98cd38, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)
[pid 316864] renameat(AT_FDCWD, "/tmp/editor_4133246938", AT_FDCWD, "/tmp/editor_4133246938.yaml" <unfinished ...>
[pid 316864] <... renameat resumed>)    = 0
[pid 316864] newfstatat(AT_FDCWD, "/opt/incus/bin/nvim",  <unfinished ...>
[pid 316864] <... newfstatat resumed>0x2a70ac98ce08, 0) = -1 ENOENT (No such file or directory)
[pid 316864] newfstatat(AT_FDCWD, "/bin/nvim",  <unfinished ...>
[pid 316864] <... newfstatat resumed>0x2a70ac98ced8, 0) = -1 ENOENT (No such file or directory)
[pid 316864] newfstatat(AT_FDCWD, "/usr/bin/nvim", 0x2a70ac98d078, 0) = -1 ENOENT (No such file or directory)
[pid 316864] newfstatat(AT_FDCWD, "/sbin/nvim",  <unfinished ...>
[pid 316864] <... newfstatat resumed>0x2a70ac98d148, 0) = -1 ENOENT (No such file or directory)
[pid 316864] newfstatat(AT_FDCWD, "/usr/sbin/nvim",  <unfinished ...>
[pid 316864] <... newfstatat resumed>0x2a70ac98d218, 0) = -1 ENOENT (No such file or directory)
[pid 316864] newfstatat(AT_FDCWD, "/usr/local/bin/nvim",  <unfinished ...>
[pid 316864] <... newfstatat resumed>0x2a70ac98d488, 0) = -1 ENOENT (No such file or directory)
[pid 316864] newfstatat(AT_FDCWD, "/usr/local/sbin/nvim", 0x2a70acd8a108, 0) = -1 ENOENT (No such file or directory)
[pid 316864] unlinkat(AT_FDCWD, "/tmp/editor_4133246938.yaml", 0 <unfinished ...>
[pid 316864] <... unlinkat resumed>)    = 0
[pid 316864] write(2, "Error: exec: \"nvim\": executable "..., 56 <unfinished ...>
Error: exec: "nvim": executable file not found in $PATH

So I think that removes mise from the equation

Doh, it’s our wrapper that’s causing the issue :wink:

See the content of /usr/bin/incus

1 Like

Ah, I think maybe we need to resolve the editor variable first here ?

diff --git a/shared/cmd/editor.go b/shared/cmd/editor.go
index 149b93795..2e2b29648 100644
--- a/shared/cmd/editor.go
+++ b/shared/cmd/editor.go
@@ -34,6 +34,11 @@ func TextEditor(inPath string, inContent []byte) ([]byte, error) {
                }
        }

+       editorPath, err := exec.LookPath(editor)
+       if err != nil {
+               return nil, fmt.Errorf("failed to find editor '%s' in PATH: %w", editor, err)
+       }
+
        if inPath == "" {
                // If provided input, create a new file
                f, err = os.CreateTemp("", "editor_")
@@ -76,7 +81,7 @@ func TextEditor(inPath string, inContent []byte) ([]byte, error) {
                path = inPath
        }

-       cmdParts := strings.Fields(editor)
+       cmdParts := strings.Fields(editorPath)
        cmd := exec.Command(cmdParts[0], append(cmdParts[1:], path)...)
        cmd.Stdin = os.Stdin
        cmd.Stdout = os.Stdout

After that I tried make client && $GOBIN/incus profile edit default and nvim opened correctly

Oh! I didn’t even think to look there. I thought I was directly interacting with the binary. That makes total sense.

1 Like

Thanks for the quick fix Stéphane :person_bowing: