hashicorp/vagrant · error · VagrantPlugins::Ansible::Errors.AnsibleCommandFailed
Ansible failed to complete successfully. Any error output sh
Error message
Ansible failed to complete successfully. Any error output should be visible above. Please fix these errors and try again.
What it means
Host-mode ansible execution shells out via Vagrant::Util::Subprocess and streams stdout/stderr to the UI detail output; a non-zero exit raises AnsibleCommandFailed. It also maps Vagrant::Errors::CommandUnavailable (ansible binary not on PATH) to AnsibleNotFoundOnHost — this specific site raises the command-failed variant only when ansible did run and failed. The actionable failure output is above the error in the log.
Source
Thrown at plugins/provisioners/ansible/provisioner/host.rb:107
def prepare_environment_variables
prepare_common_environment_variables
# Some Ansible options must be passed as environment variables,
# as there is no equivalent command line arguments
@environment_variables["ANSIBLE_HOST_KEY_CHECKING"] = "#{config.host_key_checking}"
# ANSIBLE_SSH_ARGS is required for Multiple SSH keys, SSH forwarding and custom SSH settings
@environment_variables["ANSIBLE_SSH_ARGS"] = ansible_ssh_args unless ansible_ssh_args.empty?
end
def execute_command_from_host(command)
begin
result = Vagrant::Util::Subprocess.execute(*command) do |type, data|
if type == :stdout || type == :stderr
@machine.env.ui.detail(data, new_line: false, prefix: false)
end
end
raise Ansible::Errors::AnsibleCommandFailed if result.exit_code != 0
rescue Vagrant::Errors::CommandUnavailable
raise Ansible::Errors::AnsibleNotFoundOnHost
end
end
def gather_ansible_version(package = 'ansible')
raw_output = ''
command = ['python3', '-c',
"import importlib.metadata; print('#{package} ' + importlib.metadata.version('#{package}'))"]
command << {
notify: [:stdout, :stderr]
}
begin
result = Vagrant::Util::Subprocess.execute(*command) do |type, output|
if type == :stdout && output.lines[0]
raw_output = outputView on GitHub (pinned to 35f3160f4a)
Solutions
- Read the ansible output printed just above the error — it names the failing task/host
- Confirm host->guest ssh works: use the command from `vagrant provision` output with `--verbose`, or `vagrant ssh-config` to check the port/address
- Install missing dependencies on the host (`ansible-galaxy install -r requirements.yml`) or wire them via ansible.galaxy_role_file
- Set `ansible.verbose = true` (or "vvv") and re-run `vagrant provision` for full detail
Example fix
# Vagrantfile — before (role not installed on host) config.vm.provision "ansible" do |ansible| ansible.playbook = "site.yml" # site.yml uses geerlingguy.nginx end # after — let Vagrant install roles before the run config.vm.provision "ansible" do |ansible| ansible.playbook = "site.yml" ansible.galaxy_role_file = "requirements.yml" end
Defensive patterns
Strategy: try-catch
Validate before calling
require 'mkmf'
abort 'ansible-playbook not on PATH' unless find_executable('ansible-playbook')
system('ansible-playbook', '--syntax-check', playbook_path) or abort 'playbook fails syntax check' Type guard
def ansible_playbook_runnable?(playbook_path)
!find_executable('ansible-playbook').nil? && system('ansible-playbook', '--syntax-check', playbook_path, out: File::NULL)
end Try / catch
begin machine.provision rescue Ansible::Errors::AnsibleCommandFailed # output already streamed via ui.detail; surface a summary and stop the pipeline raise 'ansible playbook failed - see provisioner output above' rescue Ansible::Errors::AnsibleNotFoundOnHost raise 'install ansible on the host first (pipx install ansible)' end
Prevention
- Run `ansible-playbook --syntax-check` on the playbook in CI before `vagrant provision`
- Pre-install roles/collections (galaxy_role_file / galaxy_collection_file) so runs don't fail on missing deps
- After `vagrant reload`, remember generated inventory addresses change - re-provision, don't cache them
When it happens
Trigger: execute_command_from_host running the assembled `ansible-playbook ...` command where Subprocess result.exit_code != 0 — failing tasks, ssh connection refused from host to guest, playbook syntax errors, missing roles on the host.
Common situations: Host cannot ssh to the guest on the forwarded port (custom ssh settings, firewalls); role/collection not installed on host; inventory generated under .vagrant/provisioners references a stale address after `vagrant reload`; ansible.cfg on the host overriding settings unexpectedly.
Related errors
- Ansible failed to complete successfully. Any error output sh
- The requested Ansible version (%{required_version}) was not
- `%{config_option}` does not exist on the %{system}: %{path}
- The requested Ansible compatibility mode (%{compatibility_mo
- Ansible Provisioner Programming Error: %{message} Internal
AI-assisted analysis of hashicorp/vagrant@35f3160f4a (2026-08-21).
Data as JSON: /api/errors/dc7950771789e4fa.
Report an issue: GitHub.