Template sensor: "this" can be "none"

Consider a sensor:

template:
  - trigger:
      - platform: state
        entity_id: xxx
        to:
    sensor:
      - name: xxx
        ...
        state: >-
          {% if ... -%}
            ...
          {%- else -%}
            {{ states(this.entity_id) }}
          {%- endif %}

When python causing a huge CPU load due to some reasons, I may get these errors in a Log:

2024-03-04 01:04:21.252 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: ‘None’ has no attribute ‘entity_id’ when rendering ‘{% if … -%}

{%- else -%}
{{ states(this.entity_id) }}
{%- endif %}’

I intentionally skipped details since they are unrelated.
The thing is that “entity_id” in only used here:

{{ states(this.entity_id) }}

So, seems that “this” can become “none” as a side effect of this “python got crazy” thing.

You’ll need to provide some fallback for the first time the sensor is created. The entity doesn’t exist yet so there’s nothing to look up in the state machine. I’d also suggest using this.state but you’ll still have to provide a default value.

Try
{{ this.state | default(0, true) }}

Change 0 to whatever you want the initial value to be.

Sounds possible.
I am using

states(this.entity_id)

only in cases like “hmm, a new possible state is bad - so keep the previous state”.
I am not 100% sure if I can use “this.state” instead.
If yes - then I will use “this.state | default(xxxx)” filter.
Could you explain what is a purpose of “true” here?
Not clear in Docs.

Also, since I need to get a previous state - probably this is a better way:

{states(this.entity_id | default('sensor.xxxxxx'))}}

or just

{states('sensor.xxxxxx')}}

but then in both cases I have to specify a particular entity_id in a template - so this cannot be reusable.

If you want to use default with variables that evaluate to false you have to set the second parameter to true

When the entity is first being created, this will render as none which evaluates to false.

In a template sensor, the contents of this is fixed as soon as the template is triggered. Therefore this will always contain the previous state while the template’s state is being rendered. If you have definitions of attributes in your template sensor, the contents of this will be the previous state as long as the rendering of the state itself didn’t trigger the entire sensor to render again.

In summary, use

{{ this.state | default(states('sensor.some_other_sensor'), true) }}

the ,true on default is useless there as the state will never resolve to a false reading, unless there’s an error in the template which results in the empty state. Even then, HA will fill that with unavailable.

That jives with my recollection but based on the error that was provided by the OP I convinced myself that was not the case:

‘None’ has no attribute ‘entity_id’

I should have just tested it to be sure

Yes, but that’s referring to the this object being None. The state property isn’t defined at that point, so the default will properly resolve because state is not defined in the None object.

| default is specifically designed to work with undefined properties on objects. Using , true allows it to work with things that are defined but return something that can be used in an if statement, like none, an emtpy list, an empty dict, an empty string, 0 or 1, boolean, etc.

I should be clear: There’s no harm in using ,True. Just trying to explain the reasoning why it’s not needed.

FWIW, when in doubt, you can use the Template Editor for experimentation.

{% set this = none %}

{{ this }}

{{ this is none }}

{{ this.state is defined }}

{{ this.state | default(42) }}

{{ this.state | default(42, true) }}


Ninja’d by petro …

sry, moving slow this morning with my original posts. Was at the bar too long :rofl:

1 Like

Thanks both. In short this will be none and therefore this.state will be undefined. And since I’m testing this.state (as opposed to this itself) the , true in the default filter doesn’t have any effect.

So, OP, you can use:

{{ this.state | default(states('sensor.some_other_sensor')) }}
1 Like

As I said, I am using the

{{ states(this.entity_id) }}

only to keep a previous value.

Before adding a support of “this” to HA, this was in a code:

{{ states('sensor.this_particular_entity_id') }}

Using “this” allowed me to use yaml-anchors or “!include” to re-use a code.

This particular error “None has no entity_id” happened when the python caused a huge CPU load during HA reboot.
Seems that some particular sensor (using “this”) was not properly initialized at this moment.

Some details:

  • there is some command_line sensor - it may get some valid state;
  • in some cases the state is bad (when a command failed);
  • when this command_line sensor was added to setup - command_line sensors did not have “availability” option yet (was added in 2024.2);
  • a state of this command_line sensor then is used in a template sensor with “availability” - the state is analysed in this template sensor;
  • if state is bad → “availability” = false; otherwise the state is processed further.

The command_line sensor is manually updated in some automation - and it is also updated on HA startup (which is not controlled by a user).
So, the template sensor is updated then as well.

Due to the mentioned “huge CPU load during HA reboot” - the template sensor was updated BEFORE it’s “this” became defined.
Have no idea WTH a sensor may be updated before it is actually constructed.
KInd of “race” may be…

As discussed, the first time the template of a template sensor is rendered, this will be none and therefore any property of the this object (such as this.entity_id or this.state or this.attributes.my_custom_attribute) will be undefined during that first rendering. There is no way around this. You have to either accept that the template will cause an error during that first evaluation or you have to handle it with logic in your template.

However if the template sensor was functioning correctly, I don’t what could cause it to have its this object render as None upon restart.

I’ll also mention again that there is no difference between {{ states(this.entity_id) }} compared to {{ this.state }} besides the fact that the latter option requires less resources to execute. They will both return the same value under all scenarios.

I would guess that a high copy load during restart would be caused by a loop and not simply by a template resulting in an error. I would look through the logs for anything relevant.

Where it was discussed? Here it was not.

This particular template sensor on every HA startup usually is assigned by the previous value. As well as some other my sensors which also use “states(this.entity_id)”.
“Usually” - means “except that particular time when I got the issue”.
I mean - “this” is defined on a 1st evaluation.

As I said, it was kind of “python issue” - occurred exactly during HA startup.
Normally “this” is not “none” on a 1st “call” on startup.

Usually , when I see similar issues with python, there are error in log. Some of them are not about a particular entity, some are like “… update of … failed because is None” and so on. Not informative. All what is informative - trying to analyse & fix.

Again, “this” usually works on a 1st evaluation.
If “this” is undefined - probably it may happen since the entity is not “constructed”.
The question is same - WTH it is allowed to resolve a state before a completion of constructing the entity?

My whole conversation with rich was discussing this.

This is only defined after the first eval, not during first eval.

OK, then I will check again my sensors. Believed that they work OK on HA startup…
Thanks everyone for answers!

If you have the full traceback from the error, we can explicitly tell you what caused the problem. Right now, you only shared the last line, which points to the this object not being instantiated at all.

Very good. Will post them then.

1 Like