# Buggy code
def manage(self):
    rc, out = self._exec(["list"])
    if rc != 0:
        self.module.fail_json(
            msg="Unable to list icinga2 features. "
            "Ensure icinga2 is installed and present in binary path."
        )

    else:
        # If feature is already in good state, just exit
        if (
            re.search("Disabled features:.* %s[ \n]" % self.module.params["name"], out)
            and self.module.params["state"] == "absent"
            or re.search(
                "Enabled features:.* %s[ \n]" % self.module.params["name"], out
            )
            and self.module.params["state"] == "present"
        ):
            self.module.exit_json(changed=False)

        if self.module.check_mode:
            self.module.exit_json(changed=True)

    if self.module.params["state"] == "present":
        feature_enable_str = "enable"
    else:
        feature_enable_str = "disable"

    rc, out = self._exec([feature_enable_str, self.module.params["name"]])

    if self.module.params["state"] == "present":
        if rc != 0:
            self.module.fail_json(
                msg="Fail to %s feature %s. icinga2 command returned %s"
                % (feature_enable_str, self.module.params["name"], out)
            )

        if re.search("already enabled", out) is None:
            change_applied = True
        else:
            change_applied = False
    else:
        if rc == 0:
            change_applied = True
        # RC is not 0 for this already disabled feature, handle it as no change applied
        elif re.search(
            "Cannot disable feature '%s'. Target file .* does not exist"
            % self.module.params["name"]
        ):
            change_applied = False
        else:
            self.module.fail_json(
                msg="Fail to disable feature. Command returns %s" % out
            )

    self.module.exit_json(changed=change_applied)


# Traceback (TypeError)
TASK [icinga2-server : Enable Icinga2 features] *******************************************
task path: /home/ansible/ansible/roles/icinga2-server/tasks/icinga2.yml:32
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/monitoring/icinga2_feature.py
<monitor.example.org> ESTABLISH SSH CONNECTION FOR USER: ansible
<monitor.example.org> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=ansible -o ConnectTimeout=10 -o ControlPath=/home/ansible/.ansible/cp/6547af9212 monitor.example.org '/bin/sh -c '"'"'sudo -H -S -n -u root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-bedifijcwlsgibsuolciioaayzpjnvhp; /usr/bin/python'"'"'"'"'"'"'"'"' &amp;&amp; sleep 0'"'"''
<monitor.example.org> (1, '', 'Traceback (most recent call last):\n  File "/tmp/ansible_i6MMOX/ansible_module_icinga2_feature.py", line 127, in <module>\n    main()\n  File "/tmp/ansible_i6MMOX/ansible_module_icinga2_feature.py", line 124, in main\n    Icinga2FeatureHelper(module).manage()\n  File "/tmp/ansible_i6MMOX/ansible_module_icinga2_feature.py", line 76, in manage\n    if re.search("Disabled features:.* %s[ \\n]" % self.module.params["name"], out) \\\n  File "/usr/lib/python2.7/re.py", line 146, in search\n    return _compile(pattern, flags).search(string)\nTypeError: expected string or buffer\n')
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_i6MMOX/ansible_module_icinga2_feature.py", line 127, in <module>
main()
File "/tmp/ansible_i6MMOX/ansible_module_icinga2_feature.py", line 124, in main
Icinga2FeatureHelper(module).manage()
File "/tmp/ansible_i6MMOX/ansible_module_icinga2_feature.py", line 76, in manage
if re.search("Disabled features:.* %s[ \n]" % self.module.params["name"], out) \
File "/usr/lib/python2.7/re.py", line 146, in search
return _compile(pattern, flags).search(string)
TypeError: expected string or buffer

failed: [monitor.example.org] (item=api) => {
"changed": false,
"failed": true,
"item": "api",
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_i6MMOX/ansible_module_icinga2_feature.py\", line 127, in <module>\n    main()\n  File \"/tmp/ansible_i6MMOX/ansible_module_icinga2_feature.py\", line 124, in main\n    Icinga2FeatureHelper(module).manage()\n  File \"/tmp/ansible_i6MMOX/ansible_module_icinga2_feature.py\", line 76, in manage\n    if re.search(\"Disabled features:.* %s[ \\n]\" % self.module.params[\"name\"], out) \\\n  File \"/usr/lib/python2.7/re.py\", line 146, in search\n    return _compile(pattern, flags).search(string)\nTypeError: expected string or buffer\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/monitoring/icinga2_feature.py
<monitor.example.org> ESTABLISH SSH CONNECTION FOR USER: ansible
<monitor.example.org> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=ansible -o ConnectTimeout=10 -o ControlPath=/home/ansible/.ansible/cp/6547af9212 monitor.example.org '/bin/sh -c '"'"'sudo -H -S -n -u root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-hdfcawsogmmfrhwhmcfyzjciphyotqqw; /usr/bin/python'"'"'"'"'"'"'"'"' &amp;&amp; sleep 0'"'"''
<monitor.example.org> (1, '', 'Traceback (most recent call last):\n  File "/tmp/ansible_yR2VVe/ansible_module_icinga2_feature.py", line 127, in <module>\n    main()\n  File "/tmp/ansible_yR2VVe/ansible_module_icinga2_feature.py", line 124, in main\n    Icinga2FeatureHelper(module).manage()\n  File "/tmp/ansible_yR2VVe/ansible_module_icinga2_feature.py", line 76, in manage\n    if re.search("Disabled features:.* %s[ \\n]" % self.module.params["name"], out) \\\n  File "/usr/lib/python2.7/re.py", line 146, in search\n    return _compile(pattern, flags).search(string)\nTypeError: expected string or buffer\n')
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_yR2VVe/ansible_module_icinga2_feature.py", line 127, in <module>
main()
File "/tmp/ansible_yR2VVe/ansible_module_icinga2_feature.py", line 124, in main
Icinga2FeatureHelper(module).manage()
File "/tmp/ansible_yR2VVe/ansible_module_icinga2_feature.py", line 76, in manage
if re.search("Disabled features:.* %s[ \n]" % self.module.params["name"], out) \
File "/usr/lib/python2.7/re.py", line 146, in search
return _compile(pattern, flags).search(string)
TypeError: expected string or buffer

failed: [monitor.example.org] (item=command) => {
"changed": false,
"failed": true,
"item": "command",
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_yR2VVe/ansible_module_icinga2_feature.py\", line 127, in <module>\n    main()\n  File \"/tmp/ansible_yR2VVe/ansible_module_icinga2_feature.py\", line 124, in main\n    Icinga2FeatureHelper(module).manage()\n  File \"/tmp/ansible_yR2VVe/ansible_module_icinga2_feature.py\", line 76, in manage\n    if re.search(\"Disabled features:.* %s[ \\n]\" % self.module.params[\"name\"], out) \\\n  File \"/usr/lib/python2.7/re.py\", line 146, in search\n    return _compile(pattern, flags).search(string)\nTypeError: expected string or buffer\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/monitoring/icinga2_feature.py
<monitor.example.org> ESTABLISH SSH CONNECTION FOR USER: ansible
<monitor.example.org> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=ansible -o ConnectTimeout=10 -o ControlPath=/home/ansible/.ansible/cp/6547af9212 monitor.example.org '/bin/sh -c '"'"'sudo -H -S -n -u root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-bkbraoemgssmthimioxrkyoqcjxfgrhm; /usr/bin/python'"'"'"'"'"'"'"'"' &amp;&amp; sleep 0'"'"''
<monitor.example.org> (1, '', 'Traceback (most recent call last):\n  File "/tmp/ansible__gk_ri/ansible_module_icinga2_feature.py", line 127, in <module>\n    main()\n  File "/tmp/ansible__gk_ri/ansible_module_icinga2_feature.py", line 124, in main\n    Icinga2FeatureHelper(module).manage()\n  File "/tmp/ansible__gk_ri/ansible_module_icinga2_feature.py", line 76, in manage\n    if re.search("Disabled features:.* %s[ \\n]" % self.module.params["name"], out) \\\n  File "/usr/lib/python2.7/re.py", line 146, in search\n    return _compile(pattern, flags).search(string)\nTypeError: expected string or buffer\n')
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible__gk_ri/ansible_module_icinga2_feature.py", line 127, in <module>
main()
File "/tmp/ansible__gk_ri/ansible_module_icinga2_feature.py", line 124, in main
Icinga2FeatureHelper(module).manage()
File "/tmp/ansible__gk_ri/ansible_module_icinga2_feature.py", line 76, in manage
if re.search("Disabled features:.* %s[ \n]" % self.module.params["name"], out) \
File "/usr/lib/python2.7/re.py", line 146, in search
return _compile(pattern, flags).search(string)
TypeError: expected string or buffer

failed: [monitor.example.org] (item=ido-mysql) => {
"changed": false,
"failed": true,
"item": "ido-mysql",
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible__gk_ri/ansible_module_icinga2_feature.py\", line 127, in <module>\n    main()\n  File \"/tmp/ansible__gk_ri/ansible_module_icinga2_feature.py\", line 124, in main\n    Icinga2FeatureHelper(module).manage()\n  File \"/tmp/ansible__gk_ri/ansible_module_icinga2_feature.py\", line 76, in manage\n    if re.search(\"Disabled features:.* %s[ \\n]\" % self.module.params[\"name\"], out) \\\n  File \"/usr/lib/python2.7/re.py\", line 146, in search\n    return _compile(pattern, flags).search(string)\nTypeError: expected string or buffer\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}

# Fixed code
def manage(self):
    rc, out = self._exec(["list"])
    if rc != 0:
        self.module.fail_json(
            msg="Unable to list icinga2 features. "
            "Ensure icinga2 is installed and present in binary path."
        )

    # If feature is already in good state, just exit
    if (
        re.search("Disabled features:.* %s[ \n]" % self.feature_name, out)
        and self.state == "absent"
    ) or (
        re.search("Enabled features:.* %s[ \n]" % self.feature_name, out)
        and self.state == "present"
    ):
        self.module.exit_json(changed=False)

    if self.module.check_mode:
        self.module.exit_json(changed=True)

    feature_enable_str = "enable" if self.state == "present" else "disable"

    rc, out = self._exec([feature_enable_str, self.feature_name])

    change_applied = False
    if self.state == "present":
        if rc != 0:
            self.module.fail_json(
                msg="Failed to %s feature %s."
                " icinga2 command returned %s"
                % (feature_enable_str, self.feature_name, out)
            )

        if re.search("already enabled", out) is None:
            change_applied = True
    else:
        if rc == 0:
            change_applied = True
        # RC is not 0 for this already disabled feature, handle it as no change applied
        elif re.search(
            "Cannot disable feature '%s'. Target file .* does not exist"
            % self.feature_name,
            out,
        ):
            change_applied = False
        else:
            self.module.fail_json(
                msg="Failed to disable feature. Command returns %s" % out
            )

    self.module.exit_json(changed=change_applied)