Ansibleエラーの修正:「Invalid data passed to loop」、リストが必要ですが <class 'dict'> が渡されました

beginner🔧 Ansible2026-07-24| Linuxディストリビューション(Ubuntu、RHEL、Debian)またはmacOS上で動作するAnsible 2.5以降。

Error Message

Invalid data passed to 'loop', it requires a list, got <class 'dict'>
#ansible#devops#troubleshooting#yaml

エラーの理解

15個のNginxバーチャルホストをデプロイするためにプレイブックを実行しており、タスクが壁に突き当たるまではすべて順順調に見えます。Ansibleは突然停止し、次の特定のエラーをスローします。

Invalid data passed to 'loop', it requires a list, got <class 'dict'>

Ansibleはここで文字通りのことを伝えています。バージョン2.5で標準となった loop キーワードは、厳密にYAMLリスト(配列)を必要とします。もしディクショナリ(波括弧で囲まれたキーと値のペアのセット)を渡すと、タスクは即座に失敗します。これは、丸い穴に四角い杭を打ち込もうとするようなものです。

なぜこれが発生するのか

ほとんどの場合、この問題はデータの構造化や取得方法が原因で発生します。主な3つの原因は以下の通りです。

  • ディクショナリの直接使用: 変数をディクショナリとして定義したが、単純なリストであるかのようにループさせようとした。
  • 登録済み変数: find のようなモジュールの出力をキャプチャしたが、その中のファイルリストではなく、結果オブジェクト全体をループさせようとしている。
  • YAML構文のミス: 変数ファイルのハイフン(-)の欠落により、意図せずリストがディクショナリになってしまっている。

ステップバイステップの修正方法

シナリオ1:実行時にディクショナリを変換する

例えば、vars/main.yml で次のようにユーザーリストが定義されているとします。

# vars/main.yml
users:
  alice: 
    uid: 1001
    shell: /bin/bash
  bob:
    uid: 1002
    shell: /bin/zsh

もし loop: "{{ users }}" を使おうとすると、Ansibleはそれをディクショナリと見なして失敗します。修正策は dict2items フィルターです。これにより、ディクショナリをAnsibleが処理できるリスト形式に再構成します。

# 修正後のタスク
- name: ディクショナリからユーザーを作成する
  ansible.builtin.user:
    name: "{{ item.key }}"
    uid: "{{ item.value.uid }}"
    shell: "{{ item.value.shell }}"
  loop: "{{ users | dict2items }}"

シナリオ2:登録済み変数の構造をたどる

これは findstat モジュールを使用する際の典型的な罠です。これらのモジュールは、メタデータ、タイムスタンプ、ステータスコードを含む巨大なディクショナリを返します。実際に必要なリストは、通常1つ下の階層に隠れています。

# 間違った方法
- name: 古いログファイルを検索する
  ansible.builtin.find:
    paths: /var/log/nginx
    patterns: "*.log.gz"
  register: found_logs

- name: ログをクリーンアップする
  ansible.builtin.file:
    path: "{{ item.path }}"
    state: absent
  loop: "{{ found_logs }}" # これは失敗します!

修正方法: ループを files 属性に向ける必要があります。そこに実際のリストが存在します。

# 正しい方法
- name: ログをクリーンアップする
  ansible.builtin.file:
    path: "{{ item.path }}"
    state: absent
  loop: "{{ found_logs.files }}" # 特定のリストをターゲットにする

シナリオ3:YAMLフォーマットのエラーを見つける

YAMLは繊細です。ハイフンを忘れると、データ構造が完全に変わってしまいます。この比較を見てください。

# 不正確:これはディクショナリです
my_packages:
  git: present
  vim: present

# 正確:これはリストです
my_packages:
  - git
  - vim

変数ファイルを確認してください。loopmy_packages を指している場合、各項目がハイフンで始まっていることを確認してください。ハイフンがないと、Ansibleはディクショナリと見なし、エラーを誘発します。

検証手順

扱っているデータ型が不明な場合は、debug モジュールと type_debug フィルターを使用して、実行中の中間変数を検査してください。推測の手間を大幅に省けます。

- name: データ型を確認する
  ansible.builtin.debug:
    msg: "変数の型は {{ users | type_debug }} です"

- name: 変換を検証する
  ansible.builtin.debug:
    msg: "フィルター適用後の型は {{ (users | dict2items) | type_debug }} です"

出力が list であれば、準備完了です。

成功のための実践的なヒント

プレイブックが大きくなるにつれて、YAMLを視覚化するのは難しくなります。行き詰まったときは、YAML to JSON変換ツールを使用してみてください。JSONはブラケット(角括弧)とブレース(波括弧)によって構造がより厳格であるため、オブジェクト(ディクショナリ)を作成したのか配列(リスト)を作成したのかが一目でわかります。

最後にもう一つのテクニック:プレイブックを -v オプションで実行してください。Ansibleは登録済み変数の完全なJSON構造を表示します。これにより、属性名を推測することなく、ループに必要なリストを保持しているキーを正確に特定できます。

Related Error Notes