hashicorp/vagrant · error · Vagrant::Errors::NFSExportsFailed

Vagrant failed to install an updated NFS exports file. This

Error message

Vagrant failed to install an updated NFS exports file. This may be
due to overly restrictive permissions on your NFS exports file. Please
validate them and try again.

command: %{command}
stdout: %{stdout}
stderr: %{stderr}

What it means

Vagrant::Errors::NFSExportsFailed raised at plugins/hosts/linux/cap/nfs.rb:199 while installing the regenerated exports file. Vagrant writes a new temp /etc/exports preserving the existing file's mode and owner; when uid/gid differ it runs `sudo chown <uid>:<gid> <tmpfile>` via Subprocess, and a non-zero exit raises with that exact command plus stdout/stderr.

Source

Thrown at plugins/hosts/linux/cap/nfs.rb:199

              # Write contents out to temporary file
              new_exports_path = File.join(Dir.tmpdir, "vagrant-exports")
              FileUtils.rm_f(new_exports_path)
              new_exports_file = File.open(new_exports_path, "w+")
              new_exports_file.puts(new_exports_content)
              new_exports_file.close

              # Ensure new file mode and uid/gid match existing file to replace
              existing_stat = File.stat(NFS_EXPORTS_PATH)
              new_stat = File.stat(new_exports_path)
              if existing_stat.mode != new_stat.mode
                File.chmod(existing_stat.mode, new_exports_path)
              end
              if existing_stat.uid != new_stat.uid || existing_stat.gid != new_stat.gid
                chown_cmd = "sudo chown #{existing_stat.uid}:#{existing_stat.gid} #{new_exports_path}"
                result = Vagrant::Util::Subprocess.execute(*Shellwords.split(chown_cmd))
                if result.exit_code != 0
                  raise Vagrant::Errors::NFSExportsFailed,
                    command: chown_cmd,
                    stderr: result.stderr,
                    stdout: result.stdout
                end
              end
              # Always force move the file to prevent overwrite prompting
              sudo_command = "sudo " if !exports_path.writable? || !exports_path.dirname.writable?
              mv_cmd = "#{sudo_command}mv -f #{new_exports_path} #{NFS_EXPORTS_PATH}"
              result = Vagrant::Util::Subprocess.execute(*Shellwords.split(mv_cmd))
              if result.exit_code != 0
                raise Vagrant::Errors::NFSExportsFailed,
                  command: mv_cmd,
                  stderr: result.stderr,
                  stdout: result.stdout
              end
            ensure
              if !new_exports_path.nil? && File.exist?(new_exports_path)
                File.unlink(new_exports_path)

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Run the exact `command:` printed in the error in a terminal to see why sudo refused
  2. Grant the user passwordless sudo for the needed commands (chown, mv, cat on the exports path) or run vagrant from an interactive shell so the sudo prompt works
  3. Make /etc/exports writable by your user (chmod/chown) so the sudo path is never taken
  4. Then `vagrant reload` to retry the exports install
Defensive patterns

Strategy: validation

Validate before calling

# Fail fast when sudo cannot run non-interactively (exports install needs chown/mv)
system("sudo -n true 2>/dev/null") || abort "Configure passwordless sudo (or run vagrant in an interactive shell)"

Try / catch

begin
  HostLinux::Cap::NFS.nfs_export(env, ui, id, ips, folders)
rescue Vagrant::Errors::NFSExportsFailed => e
  puts "command failed: #{e.data[:command]}\nstderr: #{e.data[:stderr]}"
  raise
end

Prevention

When it happens

Trigger: On a Linux host, an NFS-synced-folder up/reload stages the temp exports file and the sudo chown fails: sudo needs a password but there is no TTY, sudoers denies the command for this user, or the temp file disappeared (race/cleanup).

Common situations: CI runners or cron/daemon contexts without passwordless sudo; NOPASSWD entries that don't cover chown/mv; strict corporate sudoers policies; /etc on an unusual filesystem.

Related errors


AI-assisted analysis of hashicorp/vagrant@35f3160f4a (2026-08-21). Data as JSON: /api/errors/38864d81361a1f2c. Report an issue: GitHub.