Fix Ansible YAML Syntax Error: mapping values are not allowed in this context

beginner๐Ÿ”ง Ansible2026-03-18| Ansible 2.9+, Linux/macOS, any YAML playbook or inventory file

Error Message

ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each: YAML: mapping values are not allowed in this context
#ansible#yaml#syntax#indentation

TL;DR โ€” Quick Fix

Nine times out of ten, this error comes down to one of two things:

  • A string value contains a colon : that isn't quoted
  • Tabs crept into your indentation โ€” YAML only accepts spaces

Three steps to clear it:

  • Wrap any value containing : in double quotes: msg: "Error: connection failed"
  • Replace every tab with 2-space indentation
  • Run ansible-playbook --syntax-check playbook.yml to confirm

The Full Error

ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: Expecting value: line 1 column 1 (char 0)
YAML: mapping values are not allowed in this context
  in "<unicode string>", line 12, column 18

That line and column number is the fastest clue you have. Jump straight there before anything else โ€” don't scroll around guessing.

Root Causes

1. Unquoted colon in a string value (most common)

YAML treats : as a key-value separator. Drop one inside a string without quotes and the parser reads it as a new key โ€” which breaks everything after it.

# BROKEN โ€” YAML sees "Error" as a key
- name: Show error
  debug:
    msg: Error: connection timed out

# FIXED โ€” wrap in quotes
- name: Show error
  debug:
    msg: "Error: connection timed out"

URLs hit the same trap:

# BROKEN
  url: https://example.com/api

# FIXED
  url: "https://example.com/api"

2. Mixed tabs and spaces

YAML strictly forbids tabs for indentation. One stray tab โ€” say, from pasting code out of Slack or a PDF โ€” and the parser fails. Worse, it often points to the wrong line number.

# Spot invisible characters in vim
:set list

# Or use cat -A โ€” tabs show up as ^I
cat -A playbook.yml | grep "\^I"

3. Wrong indentation level

Ansible expects consistent 2-space indentation throughout. Mix 2-space and 4-space blocks in the same file and this error follows.

# BROKEN โ€” inconsistent indentation
- name: Install nginx
  apt:
    name: nginx
      state: present   # extra 2 spaces breaks it

# FIXED
- name: Install nginx
  apt:
    name: nginx
    state: present

4. Special characters in unquoted values

Not just colons. Any of these characters can trigger the error when left unquoted: : { } [ ] , & * # ? | - < > = ! % @ \

# BROKEN
  shell: echo hello && exit 0

# FIXED โ€” double-quote it
  shell: "echo hello && exit 0"

# Or use a literal block scalar
  shell: |
    echo hello && exit 0

How to Find and Fix the Problem

Step 1 โ€” Run syntax check first

ansible-playbook --syntax-check playbook.yml

This outputs the exact line number. Use it. Don't eyeball the file hoping to spot the issue.

Step 2 โ€” Get detailed feedback with yamllint

# Install
pip install yamllint

# Check the file
yamllint playbook.yml

# Ansible-friendly config with relaxed line length
yamllint -d "{extends: default, rules: {line-length: {max: 120}}}" playbook.yml

A single yamllint run flags tabs, bad indentation, and unquoted special chars all at once. It's faster than fixing one error at a time.

Step 3 โ€” Hunt down and remove tabs

# Find tabs โ€” grep -Pn uses Perl regex for \t
grep -Pn "\t" playbook.yml

# Replace tabs with 2 spaces in-place
sed -i 's/\t/  /g' playbook.yml

# In vim: convert tabs on the fly
:set expandtab tabstop=2
:%retab

Step 4 โ€” Confirm the fix

ansible-playbook --syntax-check playbook.yml

# Clean output looks like this:
playbook: playbook.yml

Common Patterns That Break YAML

Pattern 1 โ€” Colon in when conditions

# BROKEN โ€” the trailing ": true" is invalid here
  when: ansible_os_family == "Debian": true

# FIXED โ€” the condition evaluates to true on its own
  when: ansible_os_family == "Debian"

Pattern 2 โ€” Multi-line strings with colons

# BROKEN โ€” colon on the continuation line confuses the parser
  msg: This is a message
       with: a colon midway

# FIXED โ€” use a literal block scalar
  msg: |
    This is a message
    with: a colon midway

Pattern 3 โ€” Wrong syntax in Jinja2 default filter

# BROKEN โ€” default filter does not use a colon
  msg: "{{ my_var | default: 'fallback' }}"

# FIXED โ€” use = or pass the value as an argument
  msg: "{{ my_var | default('fallback') }}"

Tips

When I'm debugging a complex playbook that keeps throwing YAML errors, I paste the broken section into the YAML โ†” JSON Converter at ToolCraft. It converts YAML to JSON in real time, so you can instantly see where the parser fails โ€” no need to run Ansible repeatedly. Everything stays in the browser, nothing gets uploaded.

It also works in reverse: if someone sends you a JSON config and you need to put it in a playbook, convert it to YAML and the indentation is already correct.

Prevention

  • Editor settings: Set indent to 2 spaces, turn on "show invisibles" to catch tabs before they cause trouble, and enable YAML language support
  • VS Code: Install the "YAML" extension by Red Hat โ€” it validates playbooks on save and underlines problems inline
  • Add yamllint to CI: One line in your pipeline (yamllint .) catches syntax issues before any Ansible run happens
  • Commit a .yamllint config to the repo root so every team member is checked against the same rules

Quick Reference

# Always quote these patterns:
msg: "Error: something failed"       # colon in value
url: "https://example.com"           # URL
cmd: "echo foo && bar"               # special shell chars
regexp: "^\\d+: "                    # regex with colons

# Use block scalars for multi-line content:
script: |
  #!/bin/bash
  echo "Running: $1"
  exit 0

Related Error Notes