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

Ansible Provisioner Programming Error: %{message} Internal

Error message

Ansible Provisioner Programming Error:

%{message}

Internal Details:

%{details}

Sorry, but this Vagrant error should never occur.
Please check https://github.com/hashicorp/vagrant/issues for any
existing bug report. If needed, please create a new issue. Thank you!

What it means

After compatibility-mode resolution, the Ansible provisioner asserts that config.compatibility_mode is one of the concrete modes ("1.8"/"2.0", via COMPATIBILITY_MODES.slice(1..-1)). If AUTO resolution somehow left it unset, AnsibleProgrammingError is raised — this is an internal invariant violation ('should never occur'), meant to be reported as a Vagrant bug, with details naming the offending value.

Source

Thrown at plugins/provisioners/ansible/provisioner/base.rb:97

              # when more compatibility modes come... but so far let's keep it simple!
              raise Ansible::Errors::AnsibleCompatibilityModeConflict,
                ansible_version: @gathered_version,
                system: @control_machine,
                compatibility_mode: config.compatibility_mode
            end
          end

          if config.compatibility_mode == Ansible::COMPATIBILITY_MODE_AUTO
            config.compatibility_mode = Ansible::SAFE_COMPATIBILITY_MODE

            @machine.env.ui.warn(I18n.t("vagrant.provisioners.ansible.compatibility_mode_not_detected",
              compatibility_mode: config.compatibility_mode,
              gathered_version: @gathered_version_stdout) +
            "\n")
          end

          unless Ansible::COMPATIBILITY_MODES.slice(1..-1).include?(config.compatibility_mode)
            raise Ansible::Errors::AnsibleProgrammingError,
              message: "The config.compatibility_mode must be correctly set at this stage!",
              details: "config.compatibility_mode: '#{config.compatibility_mode}'"
          end

          @lexicon = ANSIBLE_PARAMETER_NAMES[config.compatibility_mode]
        end

        def check_files_existence
          check_path_is_a_file(config.playbook, :playbook)

          check_path_exists(config.inventory_path, :inventory_path) if config.inventory_path
          check_path_is_a_file(config.config_file, :config_file) if config.config_file
          check_path_is_a_file(config.extra_vars[1..-1], :extra_vars) if has_an_extra_vars_file_argument
          check_path_is_a_file(config.galaxy_role_file, :galaxy_role_file) if config.galaxy_role_file
          check_path_is_a_file(config.vault_password_file, :vault_password_file) if config.vault_password_file
        end

        def get_environment_variables_for_shell_execution

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Update Vagrant to the latest patch release — internal invariant bugs here are fixed upstream
  2. Pin `ansible.compatibility_mode = "1.8"` (or "2.0") explicitly so AUTO resolution is skipped entirely
  3. Search/file an issue at https://github.com/hashicorp/vagrant/issues including the Internal Details from the message and the provisioner log (`VAGRANT_LOG=debug vagrant provision`)

Example fix

# Vagrantfile — before
ansible.compatibility_mode = "auto"   # hits internal error when version probing fails
# after — skip AUTO resolution entirely
ansible.compatibility_mode = "2.0"
Defensive patterns

Strategy: try-catch

Validate before calling

valid_modes = %w[1.8 2.0]
abort 'pin compatibility_mode before provisioning' unless valid_modes.include?(ansible_config.compatibility_mode)

Type guard

def concrete_compatibility_mode?(mode)
  %w[1.8 2.0].include?(mode.to_s)
end

Try / catch

begin
  machine.provision
rescue Ansible::Errors::AnsibleProgrammingError => e
  # internal bug: capture e.extra_data[:details] and report upstream
  BugTracker.report('ansible-provisioner', details: e.extra_data[:details])
  raise
end

Prevention

When it happens

Trigger: set_and_check_compatibility_mode reaching the `unless COMPATIBILITY_MODES.slice(1..-1).include?(...)` check with compatibility_mode still "auto" or an unexpected value — only possible via a bug in the resolution flow (e.g. gather_ansible_version failed silently while detect_compatibility_mode was skipped).

Common situations: Practically never seen in normal use; if it appears, it follows a failed version-gathering step (ansible missing, python probing error logged just above) combined with AUTO mode, or a Vagrant regression in the provisioner — check the matching GitHub issue tracker.

Related errors


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