# Buggy code
def _normalize_parameters(self, thing, action=None, additional_args=dict()):
    """
    arguments can be fuzzy.  Deal with all the forms.
    """

    # final args are the ones we'll eventually return, so first update
    # them with any additional args specified, which have lower priority
    # than those which may be parsed/normalized next
    final_args = dict()
    if additional_args:
        if isinstance(additional_args, string_types):
            templar = Templar(loader=None)
            if templar._contains_vars(additional_args):
                final_args["_variable_params"] = additional_args
            else:
                raise AnsibleParserError(
                    "Complex args containing variables cannot use bare variables, and must use the full variable style ('{{var_name}}')"
                )
        elif isinstance(additional_args, dict):
            final_args.update(additional_args)
        else:
            raise AnsibleParserError(
                'Complex args must be a dictionary or variable string ("{{var}}").'
            )

    # how we normalize depends if we figured out what the module name is
    # yet.  If we have already figured it out, it's an 'old style' invocation.
    # otherwise, it's not

    if action is not None:
        args = self._normalize_old_style_args(thing, action)
    else:
        (action, args) = self._normalize_new_style_args(thing)

        # this can occasionally happen, simplify
        if args and "args" in args:
            tmp_args = args.pop("args")
            if isinstance(tmp_args, string_types):
                tmp_args = parse_kv(tmp_args)
            args.update(tmp_args)

    # only internal variables can start with an underscore, so
    # we don't allow users to set them directy in arguments
    if args and action not in (
        "command",
        "win_command",
        "shell",
        "win_shell",
        "script",
        "raw",
    ):
        for arg in args:
            if arg.startswith("_ansible_"):
                raise AnsibleError(
                    "invalid parameter specified for action '%s': '%s'" % (action, arg)
                )

    # finally, update the args we're going to return with the ones
    # which were normalized above
    if args:
        final_args.update(args)

    return (action, final_args)


# Traceback (AttributeError)
the full traceback was:

Traceback (most recent call last):
File "/home/jtanner/workspace/issues/AMC-3742/ansible/bin/ansible-playbook", line 92, in <module>
exit_code = cli.run()
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/cli/playbook.py", line 154, in run
results = pbex.run()
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/executor/playbook_executor.py", line 72, in run
pb = Playbook.load(playbook_path, variable_manager=self._variable_manager, loader=self._loader)
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/__init__.py", line 53, in load
pb._load_playbook_data(file_name=file_name, variable_manager=variable_manager)
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/__init__.py", line 98, in _load_playbook_data
entry_obj = Play.load(entry, variable_manager=variable_manager, loader=self._loader)
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/play.py", line 115, in load
return p.load_data(data, variable_manager=variable_manager, loader=loader)
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/base.py", line 206, in load_data
self._attributes[name] = method(name, ds[name])
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/play.py", line 167, in _load_tasks
return load_list_of_blocks(ds=ds, play=self, variable_manager=self._variable_manager, loader=self._loader)
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/helpers.py", line 58, in load_list_of_blocks
loader=loader
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/block.py", line 81, in load
return b.load_data(data, variable_manager=variable_manager, loader=loader)
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/base.py", line 206, in load_data
self._attributes[name] = method(name, ds[name])
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/block.py", line 117, in _load_block
use_handlers=self._use_handlers,
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/helpers.py", line 240, in load_list_of_tasks
t = Task.load(task_ds, block=block, role=role, task_include=task_include, variable_manager=variable_manager, loader=loader)
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/task.py", line 135, in load
return t.load_data(data, variable_manager=variable_manager, loader=loader)
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/base.py", line 195, in load_data
ds = self.preprocess_data(ds)
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/playbook/task.py", line 175, in preprocess_data
(action, args, delegate_to) = args_parser.parse()
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/parsing/mod_args.py", line 293, in parse
action, args = self._normalize_parameters(value, action=action, additional_args=additional_args)
File "/home/jtanner/workspace/issues/AMC-3742/ansible/lib/ansible/parsing/mod_args.py", line 171, in _normalize_parameters
if arg.startswith('_ansible_'):
AttributeError: 'int' object has no attribute 'startswith'

# Fixed code
def _normalize_parameters(self, thing, action=None, additional_args=dict()):
    """
    arguments can be fuzzy.  Deal with all the forms.
    """

    # final args are the ones we'll eventually return, so first update
    # them with any additional args specified, which have lower priority
    # than those which may be parsed/normalized next
    final_args = dict()
    if additional_args:
        if isinstance(additional_args, string_types):
            templar = Templar(loader=None)
            if templar._contains_vars(additional_args):
                final_args["_variable_params"] = additional_args
            else:
                raise AnsibleParserError(
                    "Complex args containing variables cannot use bare variables, and must use the full variable style ('{{var_name}}')"
                )
        elif isinstance(additional_args, dict):
            final_args.update(additional_args)
        else:
            raise AnsibleParserError(
                'Complex args must be a dictionary or variable string ("{{var}}").'
            )

    # how we normalize depends if we figured out what the module name is
    # yet.  If we have already figured it out, it's an 'old style' invocation.
    # otherwise, it's not

    if action is not None:
        args = self._normalize_old_style_args(thing, action)
    else:
        (action, args) = self._normalize_new_style_args(thing)

        # this can occasionally happen, simplify
        if args and "args" in args:
            tmp_args = args.pop("args")
            if isinstance(tmp_args, string_types):
                tmp_args = parse_kv(tmp_args)
            args.update(tmp_args)

    # only internal variables can start with an underscore, so
    # we don't allow users to set them directy in arguments
    if args and action not in (
        "command",
        "win_command",
        "shell",
        "win_shell",
        "script",
        "raw",
    ):
        for arg in args:
            arg = to_text(arg)
            if arg.startswith("_ansible_"):
                raise AnsibleError(
                    "invalid parameter specified for action '%s': '%s'" % (action, arg)
                )

    # finally, update the args we're going to return with the ones
    # which were normalized above
    if args:
        final_args.update(args)

    return (action, final_args)