hashicorp/vagrant · error · Vagrant::Errors::EnvironmentLockedError
Vagrant attempted to acquire a lock named '%{name}', but thi
Error message
Vagrant attempted to acquire a lock named '%{name}', but this
lock is being held by another instance of Vagrant already. Please
wait and try again. What it means
Raised as Vagrant::Errors::EnvironmentLockedError from Vagrant::Environment#lock (lib/vagrant/environment.rb:633) when flock(File::LOCK_EX | File::LOCK_NB) on data_dir/lock.<name>.lock keeps returning false (another Vagrant instance holds it) and opts[:retry] is false. With retry: true the method sleeps 0.2s and loops instead; the lock is per local-data-directory, so only Vagrants sharing the same .vagrant dir contend.
Source
Thrown at lib/vagrant/environment.rb:633
# This allows multiple locks in the same process to be nested
return yield if @locks[name] || opts[:noop]
# The path to this lock
lock_path = data_dir.join("lock.#{name}.lock")
@logger.debug("Attempting to acquire process-lock: #{name}")
lock("dotlock", noop: name == "dotlock", retry: true) do
f = File.open(lock_path, "w+")
end
# The file locking fails only if it returns "false." If it
# succeeds it returns a 0, so we must explicitly check for
# the proper error case.
while f.flock(File::LOCK_EX | File::LOCK_NB) === false
@logger.warn("Process-lock in use: #{name}")
if !opts[:retry]
raise Errors::EnvironmentLockedError,
name: name
end
sleep 0.2
end
@logger.info("Acquired process lock: #{name}")
result = nil
begin
# Mark that we have a lock
@locks[name] = true
result = yield
ensure
# We need to make sure that no matter what this is always
# reset to false so we don't think we have a lock when we
# actually don't.View on GitHub (pinned to 35f3160f4a)
Solutions
- Find the holder with `ps aux | grep vagrant` and wait for it to finish or stop it — flock is released automatically on process exit, so there are no stale locks to delete
- Retry the command once the other invocation completes
- Serialize access in CI (single job lane, or wrap commands in `flock /path/.vagrant/lock.global.lock vagrant ...`)
- If you call env.lock yourself, pass retry: true to block until the lock frees instead of failing fast
Example fix
# before
env.lock("global", retry: false) { env.cli(%w[up]) }
# after
env.lock("global", retry: true) { env.cli(%w[up]) } Defensive patterns
Strategy: retry
Try / catch
def with_vagrant_lock(env, name, tries: 5, delay: 0.5)
begin
env.lock(name, retry: false) { yield }
rescue Vagrant::Errors::EnvironmentLockedError
tries -= 1
raise if tries.zero?
sleep delay
delay *= 2
retry
end
end Prevention
- Never run two vagrant commands concurrently against one project/.vagrant dir
- Serialize CI stages that touch the same environment (job lanes or flock wrappers)
- Remember locks self-release on process exit — never delete lock.*.lock files to 'fix' contention
When it happens
Trigger: Two vagrant processes touching the same environment at once — e.g. `vagrant provision` while `vagrant up` runs — on a code path that calls env.lock(name) without retry: true; custom tooling invoking Environment#lock with retry: false; parallel CI jobs sharing one checkout and its .vagrant directory.
Common situations: Overlapping cron and interactive runs; a hung vagrant Ruby process still holding the flock; CI pipelines that start multiple vagrant stages concurrently on the same workspace.
Related errors
- Download to global Vagrant location already in progress. Thi
- The requested Vagrant action is locked. This may be caused b
- This Vagrant environment has specified that it requires the
- A URL to a Vagrant Cloud server is not set, so boxes cannot
- The box '%{name}' could not be found or could not be accesse
AI-assisted analysis of hashicorp/vagrant@35f3160f4a (2026-08-21).
Data as JSON: /api/errors/0f93cb644aeb9667.
Report an issue: GitHub.