{"record":{"id":"34b5f273024daa5f","repo":"ansible/ansible","slug":"the-value-of-the-task-args-keyword-is-invalid","errorCode":null,"errorMessage":"The value of the task `args` keyword is invalid.","messagePattern":"The value of the task `args` keyword is invalid\\.","errorType":"validation","errorClass":"AnsibleParserError","httpStatus":null,"severity":"error","filePath":"lib/ansible/parsing/mod_args.py","lineNumber":174,"sourceCode":"        # final args are the ones we'll eventually return, so first update\n        # them with any additional args specified, which have lower priority\n        # than those which may be parsed/normalized next\n        final_args = dict()\n\n        if additional_args is not Sentinel:\n            if isinstance(additional_args, str) and _jinja_bits.is_possibly_all_template(additional_args):\n                final_args['_variable_params'] = additional_args\n            elif isinstance(additional_args, dict):\n                final_args.update(additional_args)\n            elif additional_args is None:\n                Display().deprecated(\n                    msg=\"Ignoring empty task `args` keyword.\",\n                    version=\"2.23\",\n                    help_text='A mapping or template which resolves to a mapping is required.',\n                    obj=self._task_ds,\n                )\n            else:\n                raise AnsibleParserError(\n                    message='The value of the task `args` keyword is invalid.',\n                    help_text='A mapping or template which resolves to a mapping is required.',\n                    obj=additional_args,\n                )\n\n        # how we normalize depends if we figured out what the module name is\n        # yet.  If we have already figured it out, it's a 'new style' invocation.\n        # otherwise, it's not\n\n        if action is not None:\n            args = self._normalize_new_style_args(thing, action, additional_args)\n        else:\n            (action, args) = self._normalize_old_style_args(thing)\n\n            # this can occasionally happen, simplify\n            if args and 'args' in args:\n                tmp_args = args.pop('args')\n                if isinstance(tmp_args, str):","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/ansible/ansible/blob/9cf16a4aca7898481c257f1e17ad28d0b67b1f85/lib/ansible/parsing/mod_args.py#L156-L192","documentation":"ModuleArgsParser validates the task-level `args` keyword: it must be a mapping, a string that is possibly an all-Jinja template (deferred), or None (deprecated-empty). Any other type — list, int, bool — raises AnsibleParserError 'The value of the task `args` keyword is invalid' with help text requiring a mapping or template resolving to one.","triggerScenarios":"A task like `- copy: ...` plus `args: [src, dest]` (list), or `args: 42`; a Jinja expression resolving to a non-mapping string that is not recognized as fully templated.","commonSituations":"YAML indentation errors turning the args mapping into a string/scalar; copy-pasting k=v strings into args; migrating old shorthand args into the args keyword incorrectly.","solutions":["Make args a proper YAML mapping: args: {src: x, dest: y}","If args must be dynamic, use a single Jinja expression that resolves to a dict: args: \"{{ item.args }}\"","Remove the args keyword and put parameters directly under the module name"],"exampleFix":"# before\n- ansible.builtin.copy:\n    args:\n      - src\n      - dest\n\n# after\n- ansible.builtin.copy:\n    args:\n      src: /tmp/a\n      dest: /tmp/b","handlingStrategy":"validation","validationCode":"# Pre-flight check for dynamically built tasks\ndef task_args_ok(task: dict) -> bool:\n    a = task.get('args', '__missing__')\n    return a == '__missing__' or isinstance(a, (str, dict)) or a is None\n\nif not task_args_ok(task):\n    raise AnsibleError(f\"task 'args' must be a mapping or template, got {type(task['args']).__name__}\")","typeGuard":"def is_valid_args(value) -> bool:\n    \"\"\"task `args` must be a Mapping, all-Jinja string, or None.\"\"\"\n    if value is None or isinstance(value, dict):\n        return True\n    if isinstance(value, str) and '{{' in value and '}}' in value:\n        return True\n    return False","tryCatchPattern":null,"preventionTips":["Write args as an indented YAML mapping, never a list or scalar","ansible-playbook --syntax-check catches this before any host is contacted","When templating whole task dicts, lint the result with a schema checker"],"tags":["task-parsing","args","yaml","parser-error"],"backgroundTag":null,"analyzedSha":"9cf16a4aca7898481c257f1e17ad28d0b67b1f85","analyzedAt":"2026-08-15T00:15:47.100Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}