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

Download to global Vagrant location already in progress. Thi

Error message

Download to global Vagrant location already in progress. This
may be caused by other Vagrant processes attempting to download
a file to the same location.

Download path: %{dest_path}
Lock file path: %{lock_file_path}

What it means

Errors::DownloadAlreadyInProgress wraps Errors::VagrantLocked from Util::FileMutex: the destination file in the global Vagrant box directory is already locked by another download. Vagrant serializes writes to ~/.vagrant.d via a '<dest>.lock' file, and contention aborts the second process.

Source

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

            if File.file?(d.destination)
              env[:ui].info(I18n.t("vagrant.actions.box.download.resuming"))
            end
          end

          begin
            mutex_path = d.destination + ".lock"
            Util::FileMutex.new(mutex_path).with_lock do
              begin
                d.download!
              rescue Errors::DownloaderInterrupted
                # The downloader was interrupted, so just return, because that
                # means we were interrupted as well.
                @download_interrupted = true
                env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted"))
              end
            end
          rescue Errors::VagrantLocked
            raise Errors::DownloadAlreadyInProgress,
              dest_path: d.destination,
              lock_file_path: mutex_path
          end

          Pathname.new(d.destination)
        end

        # Tests whether the given URL points to a metadata file or a
        # box file without completely downloading the file.
        #
        # @param [String] url
        # @return [Boolean] true if metadata
        def metadata_url?(url, env)
          d = downloader(url, env, json: true, ui: false)
          env[:hook].call(:authenticate_box_downloader, downloader: d)

          # If we're downloading a file, cURL just returns no
          # content-type (makes sense), so we just test if it is JSON

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Wait for the other Vagrant process to finish, then retry the command.
  2. Identify the holder: lsof / ps aux | grep vagrant - if none, the lock is stale.
  3. Remove the stale lock file at the path printed in the error (e.g. rm /path/to/box.lock) once no process holds it.
  4. In CI, serialize box downloads or give each job an isolated VAGRANT_HOME.

Example fix

# before: two shells run simultaneously
vagrant box add ubuntu/jammy64   # -> DownloadAlreadyInProgress (lock held by other process)

# after: wait for first to finish, or if no vagrant runs:
ps aux | grep '[v]agrant' || rm "$(vagrant box list >/dev/null; echo $HOME/.vagrant.d/boxes/... )"
# simplest stale-lock cleanup (no vagrant processes running):
find ~/.vagrant.d -name '*.lock' -delete
Defensive patterns

Strategy: retry

Validate before calling

lock = File.join(dest_dir, File.basename(dest) + ".lock")
if File.exist?(lock) && !process_holds_lock?(lock)
  File.delete(lock)  # clear stale lock before vagrant runs
end

Type guard

def lock_free?(lock_path)
  !File.exist?(lock_path) || `fuser #{lock_path} 2>/dev/null`.empty?
end

Try / catch

attempts = 0
begin
  env.cli("box", "add", name)
rescue Vagrant::Errors::DownloadAlreadyInProgress => e
  attempts += 1
  # e.extra_data[:dest_path], [:lock_file_path]
  retry if attempts < 5   # other process usually finishes soon
  raise
end

Prevention

When it happens

Trigger: Two vagrant box add / vagrant up (auto box download) processes race for the same box file; Util::FileMutex#with_lock on d.destination + '.lock' raises Errors::VagrantLocked, which is rescued and re-raised as DownloadAlreadyInProgress with dest_path and lock_file_path.

Common situations: Parallel CI jobs sharing a cached ~/.vagrant.d; running 'vagrant up' on multiple machines/projects simultaneously; a crashed previous run left a stale .lock file behind; concurrent plugin-driven downloads.

Related errors


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