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

The box '%{name}' is not a versioned box. The box was added

Error message

The box '%{name}' is not a versioned box. The box was added directly instead of from a box catalog. Vagrant can only check the versions of boxes that were added from a catalog such as from the public Vagrant Server.

What it means

BoxUpdateNoMetadata is raised by Box#has_update? (lib/vagrant/box.rb:191) when @metadata_url is nil, meaning the box was added from a bare .box file rather than from a versioned catalog. Only boxes with a catalog metadata URL carry version information, so update checks are impossible for them.

Source

Thrown at lib/vagrant/box.rb:191

        message: e.extra_data[:message]
    ensure
      tf.unlink if tf
    end

    # Checks if the box has an update and returns the metadata, version,
    # and provider. If the box doesn't have an update that satisfies the
    # constraints, it will return nil.
    #
    # This will potentially make a network call if it has to load the
    # metadata from the network.
    #
    # @param [String] version Version constraints the update must
    #   satisfy. If nil, the version constrain defaults to being a
    #   larger version than this box.
    # @return [Array]
    def has_update?(version=nil, download_options: {})
      if !@metadata_url
        raise Errors::BoxUpdateNoMetadata, name: @name
      end

      if download_options.delete(:automatic_check) && !automatic_update_check_allowed?
        @logger.info("Skipping box update check")
        return
      end

      version += ", " if version
      version ||= ""
      version += "> #{@version}"
      md      = self.load_metadata(download_options)
      newer   = md.version(version, provider: @provider, architecture: @architecture)
      
      return nil if newer == nil || !md.compatible_version_update?(@version, newer.version, provider: @provider, architecture: @architecture)

      [md, newer, newer.provider(@provider, @architecture)]
    end

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Re-add the box from a catalog (host a metadata.json with versions/providers and run 'vagrant box add <metadata-url> --name x') so version tracking works
  2. If updates are not needed, stop invoking outdated/update checks on this box and set config.vm.box_check_update = false
  3. Remove the ambiguity: keep versioned boxes in Vagrant Cloud or an internal catalog and reference them by name, not by .box path

Example fix

# before: unversioned add
vagrant box add ./mybox_virtualbox.box --name corp/mybox

# after: versioned catalog add
vagrant box add https://boxes.corp/mybox/metadata.json --name corp/mybox
Defensive patterns

Strategy: validation

Validate before calling

skip_update_check = box.metadata_url.nil? # only catalog boxes are versioned
box.has_update? unless skip_update_check

Prevention

When it happens

Trigger: Calling box.has_update? (or running 'vagrant box outdated' / 'vagrant box update' / Vagrantfile box_check_update) on a box added via 'vagrant box add /path/file.box --name x' — such boxes have no metadata_url, so the guard at the top of has_update? raises immediately.

Common situations: Teams distributing internal .box files directly instead of hosting a catalog metadata.json; CI images added offline; users expecting 'vagrant box outdated' to work on locally-built boxes.

Related errors


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