hashicorp/vagrant · info · Vagrant::Errors::VagrantInterrupt
Vagrant exited after cleanup due to external interrupt.
Error message
Vagrant exited after cleanup due to external interrupt.
What it means
VagrantInterrupt is raised by Action::Warden#call at lib/vagrant/action/warden.rb:35 before the next middleware is dispatched when env[:interrupted] is truthy. The flag is set by Action::Runner's signal handler after the process receives SIGINT (Ctrl-C). Raising here lets the warden's rescue block run each middleware's recover handler, so cleanup executes before the process exits with this message.
Source
Thrown at lib/vagrant/action/warden.rb:35
# interest except to those who are curious about the internal workings
# of Vagrant.
class Warden
attr_accessor :actions, :stack
def initialize(actions, env)
@stack = []
@actions = actions.map { |m| finalize_action(m, env) }.flatten
@logger = Log4r::Logger.new("vagrant::action::warden")
@last_error = nil
end
def call(env)
return if @actions.empty?
begin
# Call the next middleware in the sequence, appending to the stack
# of "recoverable" middlewares in case something goes wrong!
raise Errors::VagrantInterrupt if env[:interrupted]
action = @actions.shift
@logger.info("Calling IN action: #{action}")
@stack.unshift(action).first.call(env)
raise Errors::VagrantInterrupt if env[:interrupted]
@logger.info("Calling OUT action: #{action}")
rescue SystemExit, NoMemoryError
# This means that an "exit" or "abort" was called, or we have run out
# of memory. In these cases, we just exit immediately.
raise
rescue Exception => e
# We guard this so that the Warden only outputs this once for
# an exception that bubbles up.
if e != @last_error
@logger.error("Error occurred: #{e}")
@last_error = e
end
env["vagrant.error"] = eView on GitHub (pinned to 35f3160f4a)
Solutions
- Treat it as expected behavior: the action was aborted and cleaned up; simply re-run the vagrant command when ready
- If interrupts are unwanted, avoid sending SIGINT to the process (stop CI timeouts or wrapper scripts that kill the process)
- If it appears without any Ctrl-C, check for parent processes or supervisors (systemd, docker stop, watchmedos) sending signals to vagrant
Defensive patterns
Strategy: try-catch
Try / catch
begin env.machine_action(:up, ...) # or CLI invocation rescue Vagrant::Errors::VagrantInterrupt # expected on SIGINT: cleanup already ran via warden recover exit 130 # conventional SIGINT exit code end
Prevention
- In automation, give vagrant a generous timeout instead of SIGINT-killing it mid-action
- Document that the first Ctrl-C triggers graceful cleanup and this message; a second Ctrl-C aborts immediately
When it happens
Trigger: User presses Ctrl-C while a middleware chain (vagrant up, halt, destroy, provision) is between actions; Runner traps SIGINT, sets environment[:interrupted] = true (lib/vagrant/action/runner.rb:96), and the next time warden.rb:35 is reached the interrupt error is raised before @actions.shift runs.
Common situations: Long-running 'vagrant up' aborted with Ctrl-C; CI jobs killed by timeout signals; scripts piping SIGINT to a vagrant process; a second interrupt arriving right as an action boundary is crossed.
Related errors
- The download was interrupted by an external signal. It did n
- The upload was interrupted by an external signal. It did not
- The Docker provider is unable to connect the container to th
- This Vagrant environment has specified that it requires the
- A URL to a Vagrant Cloud server is not set, so boxes cannot
AI-assisted analysis of hashicorp/vagrant@35f3160f4a (2026-08-21).
Data as JSON: /api/errors/362e10e80254b999.
Report an issue: GitHub.