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

NFS is reporting that your exports file is invalid. Vagrant

Error message

NFS is reporting that your exports file is invalid. Vagrant does
this check before making any changes to the file. Please correct
the issues below and execute "vagrant reload":

%{output}

What it means

Vagrant::Errors::NFSBadExports is raised by HostBSD::Cap::NFS.nfs_checkexports! right after Vagrant rewrites /etc/exports on a BSD/macOS host. Vagrant runs `nfsd checkexports` to validate the file with the OS before committing to using it, and embeds the command's stderr as %{output}. A failure means the generated VAGRANT block, or pre-existing hand-edited entries, are syntactically or semantically invalid for your nfsd.

Source

Thrown at plugins/hosts/bsd/cap/nfs.rb:212

          command = []
          command << "sudo" if !File.writable?("/etc/exports")
          command += [
            "sed", "-E", "-e",
            "/^# VAGRANT-BEGIN:( #{user})? #{id}/," +
            "/^# VAGRANT-END:( #{user})? #{id}/ d",
            "-ibak",
            "/etc/exports"
          ]

          # Use sed to just strip out the block of code which was inserted
          # by Vagrant, and restart NFS.
          system(*command)
        end

        def self.nfs_checkexports!
          r = Vagrant::Util::Subprocess.execute("nfsd", "checkexports")
          if r.exit_code != 0
            raise Vagrant::Errors::NFSBadExports, output: r.stderr
          end
        end
      end
    end
  end
end

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Read the %{output} block in the error — nfsd names the exact offending line(s) of /etc/exports
  2. Fix or delete the invalid lines; if they sit inside `# VAGRANT-BEGIN`/`# VAGRANT-END`, remove the whole block so Vagrant regenerates it from scratch
  3. Validate manually with `nfsd checkexports` until it exits 0
  4. Run `vagrant reload` so Vagrant rewrites and revalidates the exports

Example fix

# before — Vagrantfile exports the same host dir twice with different options
config.vm.synced_folder "/shared", "/srv/a", type: "nfs", mount_options: ["ro"]
config.vm.synced_folder "/shared", "/srv/b", type: "nfs", mount_options: ["rw"]
# after — one consistent permission set per host path
config.vm.synced_folder "/shared", "/srv/a", type: "nfs", mount_options: ["rw"]
config.vm.synced_folder "/shared", "/srv/b", type: "nfs", mount_options: ["rw"]
Defensive patterns

Strategy: validation

Validate before calling

# Pre-flight on BSD/macOS: let nfsd validate /etc/exports before vagrant touches it
system("nfsd checkexports")
abort "Fix /etc/exports first (see output above)" unless $?.success?

Try / catch

begin
  machine.action_reload
rescue Vagrant::Errors::NFSBadExports => e
  puts "nfsd rejected /etc/exports:\n#{e.data[:output]}"
  # surface offending lines, offer to strip the VAGRANT block, then retry once fixed
  raise
end

Prevention

When it happens

Trigger: A BSD/macOS host with one or more `type: "nfs"` synced folders runs `vagrant up`/`vagrant reload`; Vagrant regenerates the # VAGRANT-BEGIN/END block in /etc/exports and executes `nfsd checkexports` (plugins/hosts/bsd/cap/nfs.rb:210). Any non-zero exit — malformed option list, invalid network/CIDR token, duplicate exports of one directory with conflicting options, or stray lines someone added by hand — triggers the raise.

Common situations: Hand-edited /etc/exports left with a typo; the same host directory exported by two synced folders with different options; a stale entry whose client IP/CIDR no longer matches any interface; options like alldirs/maproot used in a form the host's nfsd rejects.

Related errors


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