TL;DR — クイックフィックス
このエラーの原因は、ほぼ必ずと言っていいほど次の2つのどちらかです:
- 文字列の値にクォートされていないコロン
:が含まれている - インデントにタブが混入している — YAMLはスペースのみ受け付ける
以下の3ステップで解決できます:
:を含む値をダブルクォートで囲む:msg: "Error: connection failed"- すべてのタブを2スペースのインデントに置き換える
ansible-playbook --syntax-check playbook.ymlを実行して確認する
エラーの全文
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
表示される行番号と列番号が最大のヒントです。あちこち眺め回す前に、まずそこへ直接ジャンプしましょう。
根本原因
1. 文字列値内のクォートされていないコロン(最も一般的)
YAMLはコロン : をキーと値の区切り文字として扱います。クォートなしで文字列内にコロンを入れると、パーサーがそれを新しいキーとして読み取り、以降のすべてが壊れます。
# 壊れている — YAMLは "Error" をキーとして解釈する
- name: エラーを表示
debug:
msg: Error: connection timed out
# 修正済み — クォートで囲む
- name: エラーを表示
debug:
msg: "Error: connection timed out"
URLも同じ落とし穴にはまります:
# 壊れている
url: https://example.com/api
# 修正済み
url: "https://example.com/api"
2. タブとスペースの混在
YAMLはインデントへのタブ使用を厳しく禁止しています。SlackやPDFからコードを貼り付けた際に紛れ込んだタブが1つあるだけでパーサーが失敗します。さらに悪いことに、エラーが間違った行番号を指すことも多いです。
# vimで不可視文字を確認する
:set list
# またはcat -Aを使う — タブは^Iとして表示される
cat -A playbook.yml | grep "\^I"
3. インデントレベルの誤り
Ansibleはファイル全体を通じて一貫した2スペースのインデントを期待します。同じファイル内で2スペースと4スペースのブロックが混在すると、このエラーが発生します。
# 壊れている — インデントが不統一
- name: nginxをインストール
apt:
name: nginx
state: present # 余分な2スペースで壊れる
# 修正済み
- name: nginxをインストール
apt:
name: nginx
state: present
4. クォートされていない値内の特殊文字
コロンだけではありません。以下の文字はいずれもクォートなしで使うとエラーを引き起こす可能性があります: : { } [ ] , & * # ? | - < > = ! % @ \
# 壊れている
shell: echo hello && exit 0
# 修正済み — ダブルクォートで囲む
shell: "echo hello && exit 0"
# またはリテラルブロックスカラーを使う
shell: |
echo hello && exit 0
問題の特定と修正方法
ステップ1 — まずシンタックスチェックを実行する
ansible-playbook --syntax-check playbook.yml
正確な行番号が出力されます。それを活用しましょう。目視でファイルを眺めて問題を探そうとしないでください。
ステップ2 — yamllintで詳細なフィードバックを得る
# インストール
pip install yamllint
# ファイルをチェック
yamllint playbook.yml
# 行の長さを緩和したAnsibleフレンドリーな設定
yamllint -d "{extends: default, rules: {line-length: {max: 120}}}" playbook.yml
yamllint を一度実行するだけで、タブ、インデントの誤り、クォートされていない特殊文字をまとめて検出できます。エラーを1つずつ修正するよりもはるかに効率的です。
ステップ3 — タブを探して除去する
# タブを検索 — grep -PnはPerlの正規表現で\tを使用
grep -Pn "\t" playbook.yml
# タブを2スペースに一括置換
sed -i 's/\t/ /g' playbook.yml
# vimで: タブをその場で変換する
:set expandtab tabstop=2
:%retab
ステップ4 — 修正を確認する
ansible-playbook --syntax-check playbook.yml
# 正常な出力はこのようになります:
playbook: playbook.yml
YAMLを壊す一般的なパターン
パターン1 — whenの条件内のコロン
# 壊れている — 末尾の ": true" はここでは無効
when: ansible_os_family == "Debian": true
# 修正済み — 条件自体がtrueに評価される
when: ansible_os_family == "Debian"
パターン2 — コロンを含む複数行の文字列
# 壊れている — 継続行のコロンがパーサーを混乱させる
msg: これはメッセージです
with: 途中にコロンがある
# 修正済み — リテラルブロックスカラーを使う
msg: |
これはメッセージです
with: 途中にコロンがある
パターン3 — Jinja2のdefaultフィルターでの誤った構文
# 壊れている — defaultフィルターにコロンは使わない
msg: "{{ my_var | default: 'fallback' }}"
# 修正済み — =を使うか引数として値を渡す
msg: "{{ my_var | default('fallback') }}"
ヒント
複雑なプレイブックでYAMLエラーが繰り返し発生する場合、問題のある部分をToolCraftのYAML ↔ JSONコンバーターに貼り付けてみてください。YAMLをリアルタイムでJSONに変換するので、Ansibleを何度も実行しなくてもパーサーがどこで失敗しているかをすぐに確認できます。すべてブラウザ内で完結し、データはアップロードされません。
逆方向にも使えます。誰かからJSON設定を受け取ってプレイブックに組み込む必要がある場合、YAMLに変換すれば正しいインデントで出力されます。
予防策
- エディタの設定: インデントを2スペースに設定し、「不可視文字を表示」をオンにしてタブを事前に検出できるようにし、YAMLの言語サポートを有効にする
- VS Code: Red Hatの「YAML」拡張機能をインストールする — 保存時にプレイブックを検証し、問題をインラインで下線表示する
- CIにyamllintを追加: パイプラインに1行追加する(
yamllint .)だけで、Ansibleを実行する前にシンタックスの問題を検出できる - リポジトリのルートに
.yamllint設定をコミットすることで、チーム全員が同じルールでチェックされる
クイックリファレンス
# 以下のパターンは常にクォートする:
msg: "Error: something failed" # 値内のコロン
url: "https://example.com" # URL
cmd: "echo foo && bar" # 特殊なシェル文字
regexp: "^\\d+: " # コロンを含む正規表現
# 複数行のコンテンツにはブロックスカラーを使う:
script: |
#!/bin/bash
echo "Running: $1"
exit 0

