hashicorp/vagrant · warning

vagrant.commands.box.no_installed_boxes

Error message

vagrant.commands.box.no_installed_boxes

What it means

Warning from `vagrant box list` (plugins/commands/box/command/list.rb) when @env.boxes.all returns an empty collection — i.e. the global boxes directory (~/.vagrant.d/boxes) contains no installed boxes. It prints 'There are no installed boxes! Use `vagrant box add` to add some.' and the command exits with status 0, not an error.

Source

Thrown at plugins/commands/box/command/list.rb:30

          opts = OptionParser.new do |o|
            o.banner = "Usage: vagrant box list [options]"
            o.separator ""
            o.separator "Options:"
            o.separator ""

            o.on("-i", "--box-info", "Displays additional information about the boxes") do |i|
              options[:info] = i
            end
          end

          # Parse the options
          argv = parse_options(opts)
          return if !argv

          boxes = @env.boxes.all
          if boxes.empty?
            @env.ui.warn(I18n.t("vagrant.commands.box.no_installed_boxes"), prefix: false)
            return 0
          end

          list_boxes(boxes, options[:info])

          # Success, exit status 0
          0
        end

        private

        def list_boxes(boxes, extra_info)
          # Find the longest box name
          longest_box = boxes.max_by { |x| x[0].length }
          longest_box_length = longest_box[0].length

          # Group boxes by name and version and start iterating
          boxes.group_by { |b| [b[0], b[1]] }.each do |box_info, box_data|

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. If you expected boxes to exist, check VAGRANT_HOME (`echo $VAGRANT_HOME`) and list the actual directory (`ls ${VAGRANT_HOME:-~/.vagrant.d}/boxes`).
  2. Add a box first: `vagrant box add --provider virtualbox <name-or-url>`, or just run `vagrant up` which auto-downloads the Vagrantfile's box.
  3. If scripting around this, rely on the exit status (0) rather than output, or use `vagrant box list --format json`-style machine-readable handling instead of parsing the warning.

Example fix

# before (script assumes boxes exist)
BOXES=$(vagrant box list | wc -l)

# after (script tolerates the empty-collection warning)
vagrant box add generic/ubuntu2004 || exit 1
BOXES=$(vagrant box list | grep -c '^' || true)
Defensive patterns

Strategy: validation

Validate before calling

# Before scripting against box state
boxes_dir = File.join(ENV['VAGRANT_HOME'] || File.join(Dir.home, '.vagrant.d'), 'boxes')
has_boxes = Dir.children(boxes_dir).any? { |d| File.directory?(File.join(boxes_dir, d)) }
abort 'no boxes installed' unless has_boxes

Prevention

When it happens

Trigger: Running `vagrant box list` (with or without -i/--box-info) on a fresh install, with VAGRANT_HOME pointed at an empty/new directory, or after `vagrant box prune`/`box remove` removed the last box.

Common situations: Fresh machines or CI containers with no prior `vagrant box add`; a mis-set VAGRANT_HOME/VAGRANT_DOTFILE_PATH environment variable making Vagrant look in an unexpected directory; scripts that parse `vagrant box list` output and get confused by the warning text instead of empty output.

Related errors


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