hashicorp/vagrant · error · VagrantPlugins::Ansible::Errors.AnsibleError

`%{config_option}` does not exist on the %{system}: %{path}

Error message

`%{config_option}` does not exist on the %{system}: %{path}

What it means

Before provisioning, host-mode ansible validates configured paths (playbook, inventory_path, config_file, galaxy files) by expanding them relative to the Vagrantfile's root_path and applying a File test (file?/exist?). A failing check raises the localized AnsibleError 'config_file_not_found' naming the option and resolved absolute path. It is a plain path-existence validation on the host filesystem.

Source

Thrown at plugins/provisioners/ansible/provisioner/host.rb:333

          # Re-enable ControlPersist Ansible defaults,
          # which are lost when ANSIBLE_SSH_ARGS is defined.
          unless ssh_options.empty?
            ssh_options << "-o ControlMaster=auto"
            ssh_options << "-o ControlPersist=60s"
            # Intentionally keep ControlPath undefined to let ansible-playbook
            # automatically sets this option to Ansible default value
          end

          ssh_options.join(' ')
        end

        def check_path(path, path_test_method, option_name)
          # Checks for the existence of given file (or directory) on the host system,
          # and error if it doesn't exist.

          expanded_path = Pathname.new(path).expand_path(@machine.env.root_path)
          if !expanded_path.public_send(path_test_method)
            raise Ansible::Errors::AnsibleError,
                  _key: :config_file_not_found,
                  config_option: option_name,
                  path: expanded_path,
                  system: @control_machine
          end
        end

        def check_path_is_a_file(path, option_name)
          check_path(path, "file?", option_name)
        end

        def check_path_exists(path, option_name)
          check_path(path, "exist?", option_name)
        end

      end
    end
  end

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Compare the resolved absolute path in the error with the real file location and fix the Vagrantfile option
  2. Use paths relative to the Vagrantfile root (they are expanded with root_path), or absolute paths for outside files
  3. If the file is generated, ensure the generating provisioner/shell step runs first
  4. On case-sensitive filesystems, verify filename casing exactly

Example fix

# Vagrantfile — before
ansible.playbook = "playbok.yml"
# after
ansible.playbook = "playbook.yml"
Defensive patterns

Strategy: validation

Validate before calling

expanded = File.expand_path(relative_path, project_root)
raise "#{option_name} not found: #{expanded}" unless File.public_send(file_test, expanded) # file? or exist?

Type guard

def host_path_valid?(path, root_path, must_be_file: true)
  p = Pathname.new(path.to_s).expand_path(root_path)
  must_be_file ? p.file? : p.exist?
end

Prevention

When it happens

Trigger: check_path_is_a_file / check_path_exists (called from check_files_existence before `vagrant provision` runs ansible on the host) with a path that doesn't resolve — typo'd filename, path written relative to the project root when it's elsewhere, or files generated later by another provisioner that haven't been created yet.

Common situations: Typo in `ansible.playbook = "playbok.yml"`; playbook living outside the project while given as a relative path; inventory file created by an earlier step that was skipped; case-sensitivity differences between macOS (dev) and Linux (CI) paths.

Related errors


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