TemplateError('TypeError: argument of type 'NoneType' is not iterable') while processing template

The problem

After the home assistant started, I saw this error in the logs.

What version of Home Assistant Core has the issue?

core-2024.5.0
it also happened with older versions.

What type of installation are you running?

Home Assistant OS

Link to integration documentation on our website

Diagnostics information

Complete log:

Logger: homeassistant.components.template.template_entity
Source: components/template/template_entity.py:197
integration: Template ([documentation](https://www.home-assistant.io/integrations/template), [issues](https://github.com/home-assistant/core/issues?q=is%3Aissue+is%3Aopen+label%3A%22integration%3A+template%22))
First occurred: 4:08:21 PM (9 occurrences)
Last logged: 4:08:21 PM

    TemplateError('TypeError: argument of type 'NoneType' is not iterable') while processing template 'Template<template=({%- set ns = namespace(contactsensors=[]) -%} {%- set ns.contactsensors = states.binary_sensor | selectattr('entity_id', 'in', state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id')) | selectattr('state', 'eq', 'on') | map(attribute='name') | list -%} {{ ns.contactsensors | count }}) renders=4>' for attribute '_attr_native_value' in entity 'sensor.security_roller_shade_open_count'
    TemplateError('TypeError: argument of type 'NoneType' is not iterable') while processing template 'Template<template=({%- set ns = namespace(contactsensors=[]) -%} {%- set ns.contactsensors = states.binary_sensor | selectattr('entity_id', 'in', state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id')) | selectattr('state', 'eq', 'on') | map(attribute='name') | list -%} {{ ns.contactsensors | join(', ') }}) renders=4>' for attribute '_attr_native_value' in entity 'sensor.security_roller_shade_open_info'

Those sensors are template sensors, and the code for them is:


## sensor.security_roller_shade_open_count
    - name: "security: roller-shade open - count"
      unique_id: a50f776c-4d99-495e-89f4-29a252844e04
      icon: mdi:door-open
      state: >
        {%- set ns = namespace(contactsensors=[]) -%}
        {%- if states is not none and states.binary_sensor is not none -%}
          {%- set ns.contactsensors = states.binary_sensor 
                    | selectattr('entity_id', 'in', state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id'))
                    | selectattr('state', 'eq', 'on') 
                    | map(attribute='name') | list -%}
          {{ ns.contactsensors | count }}
        {%- endif %}

    ## sensor.security_roller_shade_open_info
    - name: "security: roller-shade open - info"
      unique_id: a50f776c-4d99-495e-89f4-29a252844e05
      icon: mdi:door-open
      state: >
        {%- set ns = namespace(contactsensors=[]) -%}
        {%- if states is not none and states.binary_sensor is not none -%}
          {%- set ns.contactsensors = states.binary_sensor 
                    | selectattr('entity_id', 'in', state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id'))
                    | selectattr('state', 'eq', 'on') 
                    | map(attribute='name') | list -%}
          {{ ns.contactsensors | join(', ') }}
        {%- endif %}

while trying to solve this problem, I added the line with

        {%- if states is not none and states.binary_sensor is not none -%}

but it did not have any effect.

It’s not clear to me what what you are trying to achieve with the If statement. You are not providing an else and I believe that is throwing the error with line | selectattr('entity_id', 'in', state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id')).

A list of contact sensors?
A count?

List

state: >
{{ states.binary_sensor | selectattr('attributes.device_class', 'defined')
| selectattr('state', 'eq', 'on') 
| map(attribute='entity_id') | list  }}

Count

state: >
{{ states.binary_sensor | selectattr('attributes.device_class', 'defined')
| selectattr('state', 'eq', 'on') 
| map(attribute='entity_id') | list | count  }}
{%- set ns = namespace(contactsensors=[]) -%}
        {%- if states is not none and states.binary_sensor is not none -%}
          {%- set ns.contactsensors = states.binary_sensor 
                    | selectattr('state', 'eq', 'on') 
                    | map(attribute='name') | list -%}
          {{ ns.contactsensors | count }}
        {%- endif %}

That part of the code filters all the binary sensors and extracts only the ones that are in the list of roller-shade; as I have a lot of binary sensors (some for doors, some for windows … ) and I’m interested only on those that are in the group binary_sensor.contact_sensors_roller_shade

This is the group definition for this sensor:

- platform: group
  name: "contact-sensors: roller-shade"
  device_class: opening
  entities:
    - binary_sensor.0_ts_roll_left_down_contact
    - binary_sensor.0_ts_roll_right_down_contact
    - binary_sensor.1_dm_roll_down_contact

I’m not an expert with home-assistant entities and the code that I have works, however after every restart I get that error …

Is there a way to write the code that will not throw that error after restart?

All of this:

      state: >
        {%- set ns = namespace(contactsensors=[]) -%}
        {%- if states is not none and states.binary_sensor is not none -%}
          {%- set ns.contactsensors = states.binary_sensor 
                    | selectattr('entity_id', 'in', state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id'))
                    | selectattr('state', 'eq', 'on') 
                    | map(attribute='name') | list -%}
          {{ ns.contactsensors | count }}
        {%- endif %}

can be reduced to this:

      state: >
        {{ state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id')
           | map('states') | select('eq', 'on') | list | count }}

You can test it in the Template Editor to confirm it reports the correct count.

However it will produce the same error message on startup if binary_sensor.contact_sensors_roller_shade is undefined when the template is evaluated. In other words, state_attr will report none if the Binary Sensor Group doesn’t exist (on startup) and then the rest of the template fails.

The implication is that, on startup, the Template Sensor is created before the Binary Sensor Group is created. To mitigate that you’ll need to avoid referencing a Binary Sensor Group in the Template Sensor. You can either explicitly list all the roller shade entities in the template or try grouping them using a legacy Group entity which might be created before a Template entity on startup.

I have no idea if this has been said, but your error is coming from this selectattr

in test requires you to check against an iterable object. state_attr returns None when it can’t find an attribute. Hence the error: argument of type 'NoneType' is not iterable

you can keep your orignal template and just change the selectattr to

| selectattr('entity_id', 'in', state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id') or [])

However I recommend you use 123’s suggestion.

thanks all for the replies.

yes it works. Do you know how I can make it work for the sensor names?

I can add an if test for none … but I wasn’t sure who caused it… I don’t know why I haven’t noticed the state_attr from inside

Later edit:
I changed with verification for state_attr, and now there is no more error at restart. The code:


    ##### roller-shade open - count  ##################################
    ## sensor.security_roller_shade_open_count
    - name: "security: roller-shade open - count"
      unique_id: a50f776c-4d99-495e-89f4-29a252844e04
      icon: mdi:door-open
      state: >
        {%- set sensors_list = state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id') -%}
        {%- if sensors_list is not none-%}
          {{ sensors_list | map('states') | select('eq', 'on') | list | count }}
        {%- endif -%}

    ##### roller-shade open - info ##################################
    ## sensor.security_roller_shade_open_info
    - name: "security: roller-shade open - info"
      unique_id: a50f776c-4d99-495e-89f4-29a252844e05
      icon: mdi:door-open
      state: >
        {%- set ns = namespace(contactsensors=[]) -%}
        {%- set sensors_list = state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id') -%}
        {%- if states is not none and states.binary_sensor is not none and sensors_list is not none -%}
          {%- set ns.contactsensors = states.binary_sensor 
                    | selectattr('entity_id', 'in', sensors_list)
                    | selectattr('state', 'eq', 'on') 
                    | map(attribute='name') | list -%}
          {{ ns.contactsensors | join(', ') }}
        {%- endif %}

Thanks everyone for the help.

Immediately after a restart, what is the Template Sensor’s value? Because you have designed the template to report nothing if the Binary Sensor Group isn’t defined.

It doesn’t appear to have a value in the logs; I’m fine with that. As this sensor is for the security system, I’m aware that the home-assistant restart should not happen while the system is armed.
My concern was with the errors, as I have a counter and alerts when a threshold is met, and it is annoying to see them.

Is there a reason you haven’t defined an availability for these sensors?

I don’t follow; what do you mean by “availability”?

On the other hand, back to the initial post, does anyone know a simpler/better solution than what I did with:

    ##### roller-shade open - info ##################################
    ## sensor.security_roller_shade_open_info
    - name: "security: roller-shade open - info"
      unique_id: a50f776c-4d99-495e-89f4-29a252844e05
      icon: mdi:door-open
      state: >
        {%- set ns = namespace(contactsensors=[]) -%}
        {%- set sensors_list = state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id') -%}
        {%- if states is not none and states.binary_sensor is not none and sensors_list is not none -%}
          {%- set ns.contactsensors = states.binary_sensor 
                    | selectattr('entity_id', 'in', sensors_list)
                    | selectattr('state', 'eq', 'on') 
                    | map(attribute='name') | list -%}
          {{ ns.contactsensors | join(', ') }}

thanks @Didgeridrew , I did not know about availability.

I updated the sensor to:


    ##### roller-shade open - info ##################################
    ## sensor.security_roller_shade_open_info
    - name: "security: roller-shade open - info"
      unique_id: a50f776c-4d99-495e-89f4-29a252844e05
      icon: mdi:door-open
      availability: "{{ states is not none and states.binary_sensor is not none and state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id') is not none }}"
      state: >
        {%- set ns = namespace(contactsensors=[]) -%}
        {%- set ns.contactsensors = states.binary_sensor 
                | selectattr('entity_id', 'in', state_attr('binary_sensor.contact_sensors_roller_shade', 'entity_id'))
                | selectattr('state', 'eq', 'on') 
                | map(attribute='name')
                | list -%}
        {{ ns.contactsensors | join(', ') }}

and with this, after a restart, the sensor becomes “unavailable”, and no errors in the logs; after a short moment get’s the correct value.