Order of variables vs condition

I’m having a hard time debugging my trigger-based template.
It feels like I’m missing something, or perhaps this is a known issue? I bet that it will turn out to be my mistake :wink:

I’m currently running HA 2025.11—maybe something has been discovered or improved in recent months?

Here is the code. It may look a bit overwhelming, but I’d really appreciate any help.

    - triggers:
        - trigger: time_pattern
          alias: time_trigger
          minutes: "/1"
      variables:
        initial_val: "{{ dict(start=none, end=none, locked=false) }}"
        old_val: "{{ state_attr('sensor.pv_ctrl_most_expensive_hours_evening_test2', 'data') or initial_val }}"
        current_date: "{{ now().date() }}"
        old_start_valid: "{{ old_val.start is not none }}"
        locked: >
          {{ true if old_start_valid and current_date == as_datetime(old_val.start).date() and now() >= as_datetime(old_val.start)
            else false if not old_start_valid or old_start_valid and current_date != as_datetime(old_val.start).date()
            else old_val.locked | default(false) }}
        new_val: >
          {% if locked %}
            {{ old_val | combine({'locked': locked})}}
          {% else %}
            {# removed code as unimportant #}
          {% endif %}
      conditions:
        - condition: template
          value_template: "{{ not (locked and old_val.locked) }}"
      sensor:
        - default_entity_id: sensor.pv_ctrl_most_expensive_hours_evening_test2
          name: Most Expensive Hours Evening Test2
          unique_id: pv_ctrl_most_expensive_hours_evening_test2
          device_class: timestamp
          icon: mdi:cash-clock
          state: >
            {% set nv = new_val | default(initial_val) %}
            {{ nv.start }}
          attributes:
            data: "{{ new_val | default(initial_val) }}"

If locked is true, the new_val is set to a modified version of old_val with locked set to true.

The main condition is supposed to guard the sensor when both locks are true. So in a situation where old_val.locked = false and locked = true, it should allow storing the new value.

That does not happen.
I’ve checked the code in the template editor and confirmed that, from a template perspective, it works as expected.

The sensor, however, remains unchanged and is not updated as long as the condition for locked is true. This makes me fairly confident that the issue lies either in the condition or in the sensor update.

For any case, here is test from template editor

 {% set initial_val = dict(start=none, end=none, locked=false) %}
 {% set old_val = dict(start  = (now() - timedelta(hours=2)).replace(second=0, microsecond=0).isoformat(),  end=(now() - timedelta(hours=1)).replace(second=0, microsecond=0).isoformat(), locked = false) %}
 {% set current_date = now().date() %}
 {% set old_start_valid = old_val.start is not none %}
 {% set locked = true if old_start_valid and current_date == as_datetime(old_val.start).date() and now() >= as_datetime(old_val.start)
            else false if not old_start_valid or old_start_valid and current_date != as_datetime(old_val.start).date()
            else old_val.locked | default(false) %}

initial_val:     {{ initial_val }}
old_val:         {{ old_val }}
current_date:    {{ current_date }}
locked:          {{ locked }}
old_start_valid: {{ old_start_valid }}
today:           {{ old_start_valid and current_date == as_datetime(old_val.start).date() }}
after_start:     {{- old_start_valid and now() >= as_datetime(old_val.start) }}
                
                  
new_val:         {% set new_val =  old_val | combine({'locked': locked}) %}
                 {{- new_val }}
condition:       {{ not (locked and old_val.locked)}}
state:           {% set nv = new_val | default(dict(start=none, end=none, locked=false)) -%}
                 {{ nv.start }}
attr.data:       {{ new_val | default(dict(start=none, end=none, locked=false)) }}

Secondary issue

I’ve also noticed that when reloading template sensors (via Developer Tools / YAML), the following errors sometimes occur:

Template variable warning: 'initial_val' is undefined when rendering '{{ new_val | default(initial_val) }}'
Template variable warning: 'locked' is undefined when rendering '{{ not (locked and old_val.locked) }}'

If you look at my YAML, these errors originate either from the sensor template or from the condition template. Note that the initial_val is a static value, not dependent on anything else, so how can it be undefined?
It seems that, occasionally, these variables are not accessible when rendering templates for condition or sensor value

Thank you in advance.

IIRC the variable current_date is going to be converted to a date string when stored as a variable, which is going to fail an equality comparison with a date object.

... and current_date == as_datetime(old_val.start).date() ...

That’s one of those YAML vs. Jinja things that won’t show up in the Template Editor.

3 Likes

You are right.
What a catch, man!!!

  template:
    - triggers:
        - trigger: time_pattern
          alias: time_trigger
          minutes: "/1"
      variables:
        current_date: "{{ now().date() }}"
      sensor:
        - name: date_test_1
          state: "{{ current_date == now().date() }}"
        - name: date_test_2
          state: "{{ as_datetime(current_date).date() == now().date() }}"

date_test_1 gets false, while date_test_2 gets true

I knew about datetime objects, but somehow missed that date falls over here too.
There are so many traps…

Thank you.
Once I validate results in the original code, I will mark you answer as the solution.