hashicorp/vagrant · warning · Vagrant::Errors::BoxServerNotSet

A URL to a Vagrant Cloud server is not set, so boxes cannot

Error message

A URL to a Vagrant Cloud server is not set, so boxes cannot be added with a
shorthand ("mitchellh/precise64") format. You may also be seeing this
error if you meant to type in a path to a box file which doesn't exist
locally on your system.

To set a URL to a Vagrant Cloud server, set the `VAGRANT_SERVER_URL`
environmental variable. Or, if you meant to use a file path, make sure
the path to the file is valid.

What it means

Raised as a UI warning inside delete_from_chef_server (chef_client.rb:145-155), reached from cleanup (chef_client.rb:39-47) when delete_node or delete_client is enabled. Vagrant wants to run `knife node delete <name>` / `knife client delete <name>` on destroy, but config.node_name is blank, so it warns 'cannot delete the %{deletable} from the Chef server because Vagrant does not know the node_name' and returns, leaving the node/client registered. Normally the base provisioner backfills node_name from config.vm.hostname or a cached vagrant-XXXXXXXX value in machine.data_dir/chef_node_name (base.rb:30-53), so the gap appears when cleanup runs on a machine that was never provisioned and has no hostname set.

Source

Thrown at lib/vagrant/action/builtin/box_add.rb:77

            # Expand the path and try to use that, if possible
            p = File.expand_path(@parser.unescape(u.gsub(/^file:\/\//, "")))
            p = Util::Platform.cygwin_windows_path(p)
            next "file://#{@parser.escape(p.gsub("\\", "/"))}" if File.file?(p)

            u
          end

          # If we received a shorthand URL ("mitchellh/precise64"),
          # then expand it properly.
          expanded = false
          # Mark if only a single url entry was provided
          single_entry = url.size == 1

          url = url.map do |url_entry|
            if url_entry =~ /^[^\/]+\/[^\/]+$/ && !File.file?(url_entry)
              server = Vagrant.server_url env[:box_server_url]
              raise Errors::BoxServerNotSet if !server

              expanded = true
              # If only a single entry, expand to both the API endpoint and
              # the direct shorthand endpoint.
              if single_entry
                url_entry = [
                  "#{server}/api/v2/vagrant/#{url_entry}",
                  "#{server}/#{url_entry}"
                ]
              else
                url_entry = "#{server}/#{url_entry}"
              end
            end

            url_entry
          end.flatten

          # Call the hook to transform URLs into authenticated URLs.

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Set the name explicitly so cleanup always works: chef.node_name = "project-web-01" (must match the node registered on the Chef server).
  2. Alternatively set config.vm.hostname = "project-web-01"; base.rb uses it as the node name during provisioner init.
  3. If the warning already fired, delete the leftovers manually: `knife node delete project-web-01` and `knife client delete project-web-01` against your chef_server_url.
  4. Re-provision once before destroying so .vagrant/.../chef_node_name is written and cleanup can find the name.

Example fix

# Vagrantfile — before
config.vm.provision "chef_client" do |chef|
  chef.chef_server_url = "https://chef.example.com/organizations/myorg"
  chef.delete_node   = true
  chef.delete_client = true
end

# after
config.vm.provision "chef_client" do |chef|
  chef.chef_server_url = "https://chef.example.com/organizations/myorg"
  chef.node_name     = "project-web-01"
  chef.delete_node   = true
  chef.delete_client = true
end
Defensive patterns

Strategy: validation

Validate before calling

# Pre-destroy check: node_name must be set or cached before `vagrant destroy`
# Vagrant caches it at .vagrant/machines/<name>/<provider>/chef_node_name after the first provision
cat .vagrant/machines/*/*/chef_node_name 2>/dev/null \
  || echo "no cached node_name — set chef.node_name (or vm.hostname) before destroy"

Type guard

def chef_node_name_known?(machine, chef_config)
  !chef_config.node_name.to_s.strip.empty? ||
    !machine.config.vm.hostname.to_s.strip.empty? ||
    machine.data_dir.join("chef_node_name").file?
end

Prevention

When it happens

Trigger: A chef_client provisioner with `chef.delete_node = true` and/or `chef.delete_client = true`, then `vagrant destroy`: node_name is nil because it was never set in the Vagrantfile, config.vm.hostname is unset, and .vagrant/machines/<name>/<provider>/chef_node_name does not exist (machine never completed a chef run, or the .vagrant data directory was wiped).

Common situations: Enabling delete_node/delete_client for server hygiene, then destroying a box that failed before its first converge; deleting or moving the .vagrant directory (which drops the cached node name); renaming the project; the node on the server was registered under a name that differs from the auto-generated one.

Related errors


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