Repository navigation
[BUG]: vfox upgrade fails with "mkdir /usr/local/bin/vfox_upgrade: permission denied" and gives no hint #741
Description
Version
v1.0.12 (the latest release is v1.0.13). The code involved is unchanged on main (10c9f96).
OS
Linux (Ubuntu 26.04 on WSL2). vfox lives in /usr/local/bin, the default target of install.sh. cmd/commands/upgrade_unix.go is built for every non-Windows OS, so macOS shares this code path (not tested).
Describe the bug
When vfox is installed in a directory the current user cannot write to, vfox upgrade prints the version check and then stops with a raw filesystem error. Nothing tells the user that the command needs more privileges, or which directory it needs to write to:
$ vfox upgrade
Current version: v1.0.12
Latest available: v1.0.13
Failed to create directory: mkdir /usr/local/bin/vfox_upgrade: permission deniedSteps to reproduce
- Have an older vfox in
/usr/local/bin(the default target ofinstall.sh, which moves the binary there withsudo). - As a regular user, run
vfox upgrade.
No root is needed to reproduce it. Copy the binary into a directory that is not writable (the file itself stays owned by the user) and run it from there:
$ mkdir ro && cp "$(command -v vfox)" ro/ && chmod 555 ro
$ ro/vfox upgrade
Current version: v1.0.12
Latest available: v1.0.13
Failed to create directory: mkdir /tmp/.../ro/vfox_upgrade: permission deniedI get the same output (exit code 1) from the v1.0.12 release binary and from a build of current main (with RuntimeVersion set to 1.0.12 locally, because main is already 1.0.13). Nothing is downloaded and nothing is left behind.
Root cause
upgradeCmd(cmd/commands/upgrade.go) stages the download in<directory of the executable>/vfox_upgrade(os.Mkdir) and later replaces the binary withos.Rename(tempExePath, exePath). Both steps need write permission on the directory that contains the executable.RequestPermission()is the step meant to deal with this. On Windows (upgrade_win.go) it checks for administrator rights and relaunchesvfox upgradeelevated through UAC. On every other OS (upgrade_unix.go) it is a stub that returnsnil, so nothing is checked and the first failing syscall becomes the error message.- The permission that matters is the directory's, not the file's. In my case
/usr/local/bin/vfoxis owned by my user (-rwxr-xr-x lingh lingh) while/usr/local/binisroot:root 755. A check of the binary's own mode or ownership would pass and the upgrade would still fail.
Expected behavior
vfox upgrade should notice, before it does any work, that it cannot replace the executable, and say so in an actionable way: which directory is not writable and what to do about it, for example re-run with sudo /usr/local/bin/vfox upgrade, or reinstall into a user directory with install.sh --user. The MSIX branch of the same function already does this kind of thing on Windows ("vfox was installed as an MSIX package and cannot self-upgrade. Install a newer .msixbundle to upgrade.").
The vfox upgrade section of docs/usage/core-commands.md also does not mention that the command needs write access to the install directory.
Possible fix
- Make
RequestPermission()inupgrade_unix.godo a real check: probe the executable's directory (for exampleos.CreateTemp(exeDir, ...)and remove the file again), and on failure return an error that names the directory and suggestssudo <full path of vfox> upgrade. A real probe also covers read-only mounts and ACLs, which the binary's own mode or ownership would not. - Keep the call where it is now, after the "already up to date" check, so users who are already up to date are not bothered.
- Optionally stage the download in
os.MkdirTemp("", "vfox_upgrade")instead of the install directory, so the install directory is touched only for the final replace. That last step needs the same permission, so the check above is still required. - Add a short note about the required permissions to the
vfox upgradedocs.
Screenshots[optional]
n/a
Activity
linghengqian commentedon Oct 29, 2026
See #742 .