hashicorp/vagrant · error · Vagrant::Errors::BoxAlreadyExists
The box you're attempting to add already exists. Remove it…
Error message
The box you're attempting to add already exists. Remove it before
adding it again or add it with the `--force` flag.
Name: %{name}
Provider: %{provider}
Version: %{version} What it means
Errors::BoxAlreadyExists is raised during add_from_direct/add_from_metadata right before download: the box collection already contains the exact name+provider+version (and architecture) being added, and env[:box_force] (the --force flag) is not set.
Solutions
- Pass --force (env[:box_force]) to overwrite the existing box entry.
- Remove the existing box first ('vagrant box remove NAME --provider P --box-version V') if you want a clean slate.
- For updates, prefer 'vagrant box update' inside the project rather than re-adding.
- In scripts, guard with 'vagrant box list' (or collection.find) before adding.
Example fix
# before vagrant box add hashicorp/bionic64 # already installed -> BoxAlreadyExists # after vagrant box add --force hashicorp/bionic64 # or remove then add vagrant box remove hashicorp/bionic64 && vagrant box add hashicorp/bionic64
Defensive patterns
Strategy: validation
Validate before calling
# Same check BoxAdd performs, done by the caller collection = env.box_collection if collection.find(name, provider, version, architecture) # already present: force overwrite or skip env[:box_force] = true end
Type guard
def box_installed?(collection, name, provider, version = nil, architecture = nil) !collection.find(name, provider, version, architecture).nil? end
Try / catch
begin
env.cli("box", "add", url)
rescue Vagrant::Errors::BoxAlreadyExists => e
# e.extra_data[:name], [:provider], [:version]
env.cli("box", "add", "--force", url)
end Prevention
- Make bootstrap scripts idempotent: check 'vagrant box list' (or collection.find) before adding.
- Use --force deliberately when re-adding to refresh a box; use 'vagrant box update' for in-place updates.
- Give CI jobs isolated VAGRANT_HOME when parallel adds are unavoidable.
When it happens
Trigger: A provider for the box is determined and env[:box_force] is falsy; env[:box_collection].find(name, provider, version, opts[:architecture]) returns an existing box; the raise carries name, provider, version.
Common situations: Re-running a bootstrap script that calls 'vagrant box add' on every run; re-adding a box to update it (wrong mental model - add does not upgrade in place); CI caching a ~/.vagrant.d between jobs.
Related errors
- The box you're attempting to add already exists. Remove it…
- The box you're attempting to add has no available version…
- The checksum of the downloaded box did not match the…
- A command must be provided when the --elevated flag is…
- A Docker command executed by Vagrant didn't complete…
AI-assisted analysis of hashicorp/vagrant@35f3160f4a (2026-08-21).
Data as JSON: /api/errors/371e5fec64289edd.
Report an issue: GitHub.
Appendix: source
Thrown at lib/vagrant/action/builtin/box_add.rb:428
# @return [Box]
def box_add(urls, name, version, provider, md_url, env, **opts)
display_architecture = opts[:architecture] == :auto ?
Util::Platform.architecture : opts[:architecture]
env[:ui].output(I18n.t(
"vagrant.box_add_with_version",
name: name,
version: version,
providers: [
provider,
display_architecture ? "(#{display_architecture})" : nil
].compact.join(" ")))
# Verify the box we're adding doesn't already exist
if provider && !env[:box_force]
box = env[:box_collection].find(
name, provider, version, opts[:architecture])
if box
raise Errors::BoxAlreadyExists,
name: name,
provider: provider,
version: version
end
end
# Now we have a URL, we have to download this URL.
box = nil
begin
box_url = nil
urls.each do |url|
show_url = nil
if url.is_a?(Array)
show_url = url[1]
url = url[0]
end
View on GitHub (pinned to 35f3160f4a)