{"record":{"id":"c1b7c7be14b86d1a","repo":"hashicorp/vagrant","slug":"a-url-to-a-vagrant-cloud-server-is-not-set-so-box","errorCode":null,"errorMessage":"A URL to a Vagrant Cloud server is not set, so boxes cannot be added with a\nshorthand (\"mitchellh/precise64\") format. You may also be seeing this\nerror if you meant to type in a path to a box file which doesn't exist\nlocally on your system.\n\nTo set a URL to a Vagrant Cloud server, set the `VAGRANT_SERVER_URL`\nenvironmental variable. Or, if you meant to use a file path, make sure\nthe path to the file is valid.","messagePattern":"A URL to a Vagrant Cloud server is not set, so boxes cannot be added with a\nshorthand \\(\"mitchellh/precise64\"\\) format\\. You may also be seeing this\nerror if you meant to type in a path to a box file which doesn't exist\nlocally on your system\\.\n\nTo set a URL to a Vagrant Cloud server, set the `VAGRANT_SERVER_URL`\nenvironmental variable\\. Or, if you meant to use a file path, make sure\nthe path to the file is valid\\.","errorType":"exception","errorClass":"Vagrant::Errors::BoxServerNotSet","httpStatus":null,"severity":"warning","filePath":"lib/vagrant/action/builtin/box_add.rb","lineNumber":77,"sourceCode":"\n            # Expand the path and try to use that, if possible\n            p = File.expand_path(@parser.unescape(u.gsub(/^file:\\/\\//, \"\")))\n            p = Util::Platform.cygwin_windows_path(p)\n            next \"file://#{@parser.escape(p.gsub(\"\\\\\", \"/\"))}\" if File.file?(p)\n\n            u\n          end\n\n          # If we received a shorthand URL (\"mitchellh/precise64\"),\n          # then expand it properly.\n          expanded = false\n          # Mark if only a single url entry was provided\n          single_entry = url.size == 1\n\n          url = url.map do |url_entry|\n            if url_entry =~ /^[^\\/]+\\/[^\\/]+$/ && !File.file?(url_entry)\n              server = Vagrant.server_url env[:box_server_url]\n              raise Errors::BoxServerNotSet if !server\n\n              expanded = true\n              # If only a single entry, expand to both the API endpoint and\n              # the direct shorthand endpoint.\n              if single_entry\n                url_entry = [\n                  \"#{server}/api/v2/vagrant/#{url_entry}\",\n                  \"#{server}/#{url_entry}\"\n                ]\n              else\n                url_entry = \"#{server}/#{url_entry}\"\n              end\n            end\n\n            url_entry\n          end.flatten\n\n          # Call the hook to transform URLs into authenticated URLs.","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/hashicorp/vagrant/blob/35f3160f4ad6edc3a9f3aa9570adfc1a4d73aaa5/lib/vagrant/action/builtin/box_add.rb#L59-L95","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Set the name explicitly so cleanup always works: chef.node_name = \"project-web-01\" (must match the node registered on the Chef server).","Alternatively set config.vm.hostname = \"project-web-01\"; base.rb uses it as the node name during provisioner init.","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.","Re-provision once before destroying so .vagrant/.../chef_node_name is written and cleanup can find the name."],"exampleFix":"# Vagrantfile — before\nconfig.vm.provision \"chef_client\" do |chef|\n  chef.chef_server_url = \"https://chef.example.com/organizations/myorg\"\n  chef.delete_node   = true\n  chef.delete_client = true\nend\n\n# after\nconfig.vm.provision \"chef_client\" do |chef|\n  chef.chef_server_url = \"https://chef.example.com/organizations/myorg\"\n  chef.node_name     = \"project-web-01\"\n  chef.delete_node   = true\n  chef.delete_client = true\nend","handlingStrategy":"validation","validationCode":"# Pre-destroy check: node_name must be set or cached before `vagrant destroy`\n# Vagrant caches it at .vagrant/machines/<name>/<provider>/chef_node_name after the first provision\ncat .vagrant/machines/*/*/chef_node_name 2>/dev/null \\\n  || echo \"no cached node_name — set chef.node_name (or vm.hostname) before destroy\"","typeGuard":"def chef_node_name_known?(machine, chef_config)\n  !chef_config.node_name.to_s.strip.empty? ||\n    !machine.config.vm.hostname.to_s.strip.empty? ||\n    machine.data_dir.join(\"chef_node_name\").file?\nend","tryCatchPattern":null,"preventionTips":["Whenever you set chef.delete_node/chef.delete_client, also set chef.node_name to the exact name registered on the Chef server.","Set config.vm.hostname — the chef provisioner base uses it as the node name fallback.","Never delete the .vagrant data directory between provisioning and destroying when node deletion matters.","Periodically audit `knife node list` for stale vagrant-* nodes that cleanup silently skipped."],"tags":["chef","chef-client","vagrant","knife","node-management"],"backgroundTag":"chef-node-cleanup-skipped","analyzedSha":"35f3160f4ad6edc3a9f3aa9570adfc1a4d73aaa5","analyzedAt":"2026-08-21T13:34:32.514Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}