# Buggy code
def remove_packages(module, pacman_path, packages):
    data = []
    diff = {
        "before": "",
        "after": "",
    }

    if module.params["recurse"] or module.params["force"]:
        if module.params["recurse"]:
            args = "Rs"
        if module.params["force"]:
            args = "Rdd"
        if module.params["recurse"] and module.params["force"]:
            args = "Rdds"
    else:
        args = "R"

    remove_c = 0
    # Using a for loop in case of error, we can report the package that failed
    for package in packages:
        # Query the package first, to see if we even need to remove
        installed, updated, unknown = query_package(module, pacman_path, package)
        if not installed:
            continue

        cmd = "%s -%s %s --noconfirm --noprogressbar" % (pacman_path, args, package)
        rc, stdout, stderr = module.run_command(cmd, check_rc=False)

        if module._diff:
            d = stdout.split("\n")[2].split(" ")[2:]
            for i, pkg in enumerate(d):
                d[i] = re.sub("-[0-9].*$", "", d[i].split("/")[-1])
                diff["before"] += "%s\n" % pkg
            data.append("\n".join(d))

        if rc != 0:
            module.fail_json(msg="failed to remove %s" % (package))

        remove_c += 1

    if remove_c > 0:
        module.exit_json(
            changed=True, msg="removed %s package(s)" % remove_c, diff=diff
        )

    module.exit_json(changed=False, msg="package(s) already absent")


# Traceback (nIndexError)
$ ansible-playbook -i inventories/development.ini installtraceback.yml
PLAY [all] ************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************************************************************************************************
ok: [devel]

TASK [Try to install a non-existing package] **************************************************************************************************************************************************************************************************
fatal: [devel]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Shared connection to 192.168.122.125 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n  File \"/tmp/ansible_nQG_Kl/ansible_module_pacman.py\", line 451, in <module>\r\n    main()\r\n  File \"/tmp/ansible_nQG_Kl/ansible_module_pacman.py\", line 443, in main\r\n    install_packages(module, pacman_path, p['state'], pkgs, pkg_files)\r\n  File \"/tmp/ansible_nQG_Kl/ansible_module_pacman.py\", line 306, in install_packages\r\n    data = stdout.split('\\n')[3].split(' ')[2:]\r\nIndexError: list index out of range\r\n", "msg": "MODULE FAILURE", "rc": 0}
to retry, use: --limit @/home/user/code/ansible/installtraceback.retry

PLAY RECAP ************************************************************************************************************************************************************************************************************************************
devel            : ok=1    changed=0    unreachable=0    failed=1

# Fixed code
def remove_packages(module, pacman_path, packages):
    data = []
    diff = {
        "before": "",
        "after": "",
    }

    if module.params["recurse"] or module.params["force"]:
        if module.params["recurse"]:
            args = "Rs"
        if module.params["force"]:
            args = "Rdd"
        if module.params["recurse"] and module.params["force"]:
            args = "Rdds"
    else:
        args = "R"

    remove_c = 0
    # Using a for loop in case of error, we can report the package that failed
    for package in packages:
        # Query the package first, to see if we even need to remove
        installed, updated, unknown = query_package(module, pacman_path, package)
        if not installed:
            continue

        cmd = "%s -%s %s --noconfirm --noprogressbar" % (pacman_path, args, package)
        rc, stdout, stderr = module.run_command(cmd, check_rc=False)

        if rc != 0:
            module.fail_json(msg="failed to remove %s" % (package))

        if module._diff:
            d = stdout.split("\n")[2].split(" ")[2:]
            for i, pkg in enumerate(d):
                d[i] = re.sub("-[0-9].*$", "", d[i].split("/")[-1])
                diff["before"] += "%s\n" % pkg
            data.append("\n".join(d))

        remove_c += 1

    if remove_c > 0:
        module.exit_json(
            changed=True, msg="removed %s package(s)" % remove_c, diff=diff
        )

    module.exit_json(changed=False, msg="package(s) already absent")