The Error
ERROR! this task 'copy' has extra params, which is only allowed in the following modules: raw, meta, include, include_tasks, import_tasks
Run ansible-playbook and it bails immediately โ no connection attempt, no host output, nothing. The fault is in the task definition itself, not on the remote host.
What Triggers This
Ansible modules accept arguments two ways:
- Free-form (inline string): only valid for
command,shell,raw,script. One string, same line as the module key. - Key=value or YAML dict: everything else โ
copy,file,apt,template, and so on.
The error triggers when you mix these styles. Usually that means parameters are placed at the task level instead of nested under the module, or an inline string is combined with YAML keys in the same task block. One misplaced argument is enough.
Common Scenarios That Cause It
Scenario 1: Extra key placed at task level instead of module level
# WRONG
- name: Copy config file
copy: src=files/app.conf dest=/etc/app/app.conf
mode: '0644' # <-- task level, not under copy:
owner: root
mode and owner land on the task dict rather than inside the module. Ansible treats them as unknown task-level keys and throws the error.
Scenario 2: Free-form string mixed with YAML dict keys
# WRONG
- name: Copy config file
copy: src=files/app.conf dest=/etc/app/app.conf
mode: '0644'
Mixing an inline key=value string with indented YAML under the same module key breaks the parser. Pick one style and stick with it.
Scenario 3: Typo โ second module key left in the task block
# WRONG
- name: Restart nginx
service:
name: nginx
state: restarted
copy: # <-- leftover from a cut-paste
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
A task can only have one module. The second module key (copy: here) becomes an unrecognized extra param โ classic copy-paste artifact.
The Fix
Nest all arguments under the module with YAML dict syntax
# CORRECT
- name: Copy config file
copy:
src: files/app.conf
dest: /etc/app/app.conf
mode: '0644'
owner: root
Every argument goes under copy: as an indented key. At the same indentation level as copy:, only standard task keywords belong: name, when, notify, tags, become, and so on.
Inline key=value also works โ but keep it all on one line
# CORRECT โ all args inline
- name: Copy config file
copy: src=files/app.conf dest=/etc/app/app.conf mode='0644' owner=root
Past three or four arguments this becomes a wall of text. YAML dict form is easier to read and review in pull requests.
Free-form modules (command, shell) work differently
# CORRECT โ shell/command use free-form
- name: Check disk usage
shell: df -h /
# CORRECT โ structured options go under args:, not mixed inline
- name: Run script with timeout
command: /opt/scripts/deploy.sh
args:
chdir: /opt/scripts
Even with free-form modules, structured options like chdir or stdin go under args:. Never inline them alongside the command string.
Quick Diagnostic
Ansible names the offending task in the error message. Find that task in your playbook and scan for:
- Any key at the task's top level that is not a standard Ansible keyword (
name,when,register,loop,notify,tags,become,ignore_errors, etc.) - Module arguments sitting one indentation level too high
- Two module keys in the same task block
Before touching any remote host, run a syntax check:
ansible-playbook site.yml --syntax-check
No SSH connections, no risk โ just a fast parse of your YAML.
Verify the Fix
# Syntax check โ should return no errors
ansible-playbook site.yml --syntax-check
# Expected output
playbook: site.yml
# Dry run to confirm task would execute correctly
ansible-playbook site.yml --check --diff
A clean --syntax-check exit means the extra params error is gone. Follow it with --check --diff to see exactly what the task would change โ still without touching the remote host.
Tips to Avoid This in the Future
- Default to YAML dict syntax for non-free-form modules. It makes indentation errors obvious at a glance.
- Add
--syntax-checkto your CI pipeline. It catches this entire class of error in under a second, before the PR merges. - Run
ansible-lintlocally. Install it withpip install ansible-lint, then runansible-lint site.yml. It flags mixed syntax and dozens of other style issues. - Install the VS Code Ansible extension (Red Hat). Structural errors show up as red squiggles while you type โ no need to run anything.

