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 = output

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Read the ansible output printed just above the error — it names the failing task/host
  2. Confirm host->guest ssh works: use the command from `vagrant provision` output with `--verbose`, or `vagrant ssh-config` to check the port/address
  3. Install missing dependencies on the host (`ansible-galaxy install -r requirements.yml`) or wire them via ansible.galaxy_role_file
  4. 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

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


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