Ansible dict object has no attribute stdout (or) stderr - How to Resolve

This post discusses how to solve the Ansible error 'dict object' has no attribute 'stdout_lines" .

This error appears when you are trying to iterate through a list or dictionary incorrectly.

In this post, we will discuss how to iterate through the dictionary and list in the right way and solve your "dict object has no attribute" error.

Some background

Ansible will throw this error when you are trying to display the stdout (or) stderr of a task during playbook runtime.

Generally, we display the stdout (or) stderr of the task at runtime by calling the corresponding task's register within the debug module and with the help of msg as shown below.

- name : Validate Java
      become: yes
      become_user: weblogic
      tags: app
      command: "java -version"
      register: javaver

    - debug:
        msg: " Java Version Found {{ javaver.stderr }}"

and the output of that debug task would look something like this,  as it runs.

TASK [debug] *************************************************************************************************************************************************
ok: [192.168.60.4] => {
    "msg": " Java Version Found java version \"1.8.0_161\"\nJava(TM) SE Runtime Environment (build 1.8.0_161-b12)\nJava HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)"
}
ok: [192.168.60.5] => {
    "msg": " Java Version Found java version \"1.8.0_161\"\nJava(TM) SE Runtime Environment (build 1.8.0_161-b12)\nJava HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)"
}

But sometimes, we will get the exception while trying to do the same thing. ( not exactly the same)

Which is trying to display the stdout of the task by invoking the <registername>.stdout within debug module's msg parameter

look at the modified version of the same task with loop iteration.

---
    hosts: app
    tasks:
      - name: Validate Java
        shell: "{{ item }}"
        become_user: weblogic
        become: yes
        register: javaout
        with_items:
           - "java -version"
           - "java -d64 -version"
      - debug: 
        msg: "{{javaout.stderr}}" 

What do you think the output of this will be ?.

An Error message states that  dict object' has no attribute 'stderr'

 

 

 

 

 

Why this error?

To understand why this error is occurring and how Ansible is saying that we are trying to print the dictionary object.

Let us make little modification in our task to print the complete register variable instead of a property (stderr (or) stdout)

The modified playbook with debug module

- name: validate Java version and Data model
      become: yes
      become_user: weblogic
      shell: "{{ item }}"
      register: javaout
      with_items:
        - "java -version"
        - "java -d64 -version"
      failed_when: "'error' in javaout.stderr"
 - debug:
       msg: "{{javaout}}" 

The Output

As mentioned in the preceding image,  "results" : [  is a key and value of a dictionar

The Reason the output came in the dictionary format is that we have used "with_items" loop along with  register so that  we can get the output for each loop iteration (or) item.

Refer this link  here for more info

 

How to resolve

Since the stdout and stderr comes inside the list  and since the list cannot be parsed with the "key"  only option is to iterate with the list with the help of loop module.

The Resolved Playbook - A Right way to process dict object

- name: validate Java version and Data model
      become: yes
      become_user: weblogic
      shell: "{{ item }}"
      register: javaout
      with_items:
        - "java -version"
        - "java -d32 -version"
      failed_when: "'error' in javaout.stderr"

    - debug:
        msg: "{{ item.stderr }}"
      loop: "{{ javaout.results }}"

    - name: fail if error in javaout output
      fail:
        msg: "Not a valid 32bit JVM. Make sure the Java support -d64 data model"
      when: "'Error' in  item.stderr "
      loop: "{{ javaout.results }}"

As you could notice, we are using the loop module to parse the register.results and accessing the stderr of the register as item.stderr  As we have a loop with the register, we will the stderr of each item.

In other words, we will see the stderr of both java commands executed on both machines

The output will clarify the same.

Note*:  If you want to access the stdout (or) stdout_lines. Just change the msg.stderr to msg.stdout (or) msg.stdout_lines accordingly.

Output

You could see that we were able to print the stderrof the task without any dictionary related error.

We learnt the correct way to process the loop variables and its contents and how to avoid dict object' has no attribute 'stdout_lines error message

Hope it helps

Thanks,

Sarav AK