ansible-collections / ansible-collections/cloud.common
`turbo_fail` crashes with `TypeError` when `params` includes `msg`
- Dominant language
- Python
- Stars
- 19
- Forks
- 28
- PR merge metrics
- No merged PRs in 30d
Description
##### SUMMARY
The `cloud.common.turbo_fail` module raises a Python `TypeError` instead of failing gracefully when the `params` dictionary contains a `msg` key. This happens because the module passes `msg` twice to `fail_json`.
##### ISSUE TYPE
- Bug Report
##### COMPONENT NAME
turbo_fail
##### ANSIBLE VERSION
```paste below
ansible [core 2.18.8]
config file = None
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.12/site-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.12.10 (main, Apr 22 2025, 00:00:00) [GCC 14.2.1 20240912 (Red Hat 14.2.1-3)] (/usr/bin/python3.12)
jinja version = 3.1.6
libyaml = True
```
##### COLLECTION VERSION
```paste below
Collection Version
------------ -------
cloud.common 4.2.0
```
##### CONFIGURATION
```paste below
```
##### OS / ENVIRONMENT
##### STEPS TO REPRODUCE
```yaml
- hosts: localhost
gather_facts: false
tasks:
- name: Run turbo_fail with conflicting msg
cloud.common.turbo_fail:
params:
msg: "user-defined message"
extra: "value"
```
##### EXPECTED RESULTS
We would expect the task to fails gracefully with a clean error message.
##### ACTUAL RESULTS
```paste below
PLAY [localhost] **********************************************************************************************************************************************************************
TASK [Run turbo_fail with conflicting msg] ********************************************************************************************************************************************
task path: /y.yml:4
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c 'echo ~root && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp `"&& mkdir "` echo /root/.ansible/tmp/ansible-tmp-1755431279.178766-247-203242999900107 `" && echo ansible-tmp-1755431279.178766-247-203242999900107="` echo /root/.ansible/tmp/ansible-tmp-1755431279.178766-247-203242999900107 `" ) && sleep 0'
Using module file /usr/local/lib/python3.12/site-packages/ansible_collections/cloud/common/plugins/modules/turbo_fail.py
<127.0.0.1> PUT /root/.ansible/tmp/ansible-local-244lpv_mr58/tmpxmesz_qt TO /root/.ansible/tmp/ansible-tmp-1755431279.178766-247-203242999900107/AnsiballZ_turbo_fail.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+rwx /root/.ansible/tmp/ansible-tmp-1755431279.178766-247-203242999900107/ /root/.ansible/tmp/ansible-tmp-1755431279.178766-247-203242999900107/AnsiballZ_turbo_fail.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3.12 /root/.ansible/tmp/ansible-tmp-1755431279.178766-247-203242999900107/AnsiballZ_turbo_fail.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1755431279.178766-247-203242999900107/ > /dev/null 2>&1 && sleep 0'
fatal: [localhost]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"params": {
"extra": "value",
"msg": "user-defined message"
}
}
},
"msg": [
" File \"\", line 198, in _run_module_as_main\n",
" File \"\", line 88, in _run_code\n",
" File \"/tmp/ansible_cloud.common.turbo_fail_payload_788tn_y6/ansible_cloud.common.turbo_fail_payload.zip/ansible_collections/cloud/common/plugins/module_utils/turbo/server.py\", line 420, in \n server.start()\n",
" File \"/tmp/ansible_cloud.common.turbo_fail_payload_788tn_y6/ansible_cloud.common.turbo_fail_payload.zip/ansible_collections/cloud/common/plugins/module_utils/turbo/server.py\", line 395, in start\n self.loop.run_forever()\n",
" File \"/usr/lib64/python3.12/asyncio/base_events.py\", line 645, in run_forever\n self._run_once()\n",
" File \"/usr/lib64/python3.12/asyncio/base_events.py\", line 1999, in _run_once\n handle._run()\n",
" File \"/usr/lib64/python3.12/asyncio/events.py\", line 88, in _run\n self._context.run(self._callback, *self._args)\n",
" File \"/tmp/ansible_cloud.common.turbo_fail_payload_788tn_y6/ansible_cloud.common.turbo_fail_payload.zip/ansible_collections/cloud/common/plugins/module_utils/turbo/server.py\", line 355, in handle\n result = await run_as_module(content, debug_mode=self.debug_mode)\n",
" File \"/tmp/ansible_cloud.common.turbo_fail_payload_788tn_y6/ansible_cloud.common.turbo_fail_payload.zip/ansible_collections/cloud/common/plugins/module_utils/turbo/server.py\", line 308, in run_as_module\n \"msg\": traceback.format_stack() + [str(e)],\n",
"Traceback (most recent call last):\n File \"/tmp/ansible_cloud.common.turbo_fail_payload_788tn_y6/ansible_cloud.common.turbo_fail_payload.zip/ansible_collections/cloud/common/plugins/module_utils/turbo/server.py\", line 208, in run\n self.module_class.main()\n File \"/tmp/ansible_cloud.common.turbo_fail_payload_788tn_y6/ansible_cloud.common.turbo_fail_payload.zip/ansible_collections/cloud/common/plugins/modules/turbo_fail.py\", line 54, in main\n run_module()\n File \"/tmp/ansible_cloud.common.turbo_fail_payload_788tn_y6/ansible_cloud.common.turbo_fail_payload.zip/ansible_collections/cloud/common/plugins/modules/turbo_fail.py\", line 49, in run_module\n module.fail_json(msg=msg, **module.params.get(\"params\"))\nTypeError: ansible_collections.cloud.common.plugins.module_utils.turbo.module.AnsibleTurboModule.fail_json() got multiple values for keyword argument 'msg'\n"
]
}
PLAY RECAP ****************************************************************************************************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
```
## Root Cause
In `run_module` the call:
```python
module.fail_json(msg=msg, **module.params.get("params"))
```
leads to duplicate keyword arguments if `params` contains a `msg` key.
Contributor guide
Research direction
Start in plugins/modules/turbo_fail.py at run_module, where module.fail_json is called with msg and the expanded params dictionary. Reproduce the issue with the provided playbook and confirm completion when a params.msg value no longer causes a TypeError and the task fails with a clean error message.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devops
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100