Can anyone see why this template sensor is returning "unknown"?

Hello, I have almost got a nice bin collection system working, but I am looking for some help to figure out exactly why one of my template sensors is returning “unknown”:

I have tested everything I can think of, and am now at a brick wall…

Here is the YAML:

template:
        
### Template sensors to keep track of how many days until each bin collection.
### These check just after midnight each day to see how long each one is

  - trigger:
      - platform: time
        at: "00:01:00"
      - platform: homeassistant
        event: start

    action:
      - action: calendar.get_events
        data:
          start_date_time: "{{ today_at() }}"
          duration:
            days: 60
        target:
          entity_id: calendar.bin_collections
        response_variable: agenda

      - variables:
          events: "{{ agenda['calendar.bin_collections']['events'] }}"

          days_recycling: >-
            {% set match = events
              | selectattr('summary', 'search', 'Recycling bin collection')
              | map(attribute='start')
              | map('as_datetime')
              | list %}
            {{ (match[0] | as_local - today_at()).days if match | length > 0 else -1 }}

          days_garden: >-
            {% set match = events
              | selectattr('summary', 'search', 'Garden bin collection')
              | map(attribute='start')
              | map('as_datetime')
              | list %}
            {{ (match[0] | as_local - today_at()).days if match | length > 0 else -1 }}

    sensor:
      - name: "Recycling bin countdown"
        unique_id: recycling_bin_countdown
        icon: mdi:trash-can
        state: >
          {% if days_recycling == -1 %}
            None upcoming
          {% elif days_recycling == 0 %}
            Today
          {% elif days_recycling == 1 %}
            Tomorrow
          {% else %}
            In {{ days_recycling }} Days
          {% endif %}

      - name: "Garden bin countdown"
        icon: mdi:trash-can
        unique_id: garden_bin_countdown
        state: >
          {% if days_garden == -1 %}
            None upcoming
          {% elif days_garden == 0 %}
            Today
          {% elif days_garden == 1 %}
            Tomorrow
          {% else %}
            In {{ days_garden }} Days
          {% endif %}

Brief description of this YAML

I have an action which runs every day just after midnight (or as well just after Home Assistant has restarted), which grabs the list of all events in my “bin collection” calendar over the next 60 days. It then takes the first upcoming one for each of recycling and garden bins, and counts the number of days until that bin collection - these get stored in the days_recycling and days_garden variables. If there is no bin collection found in the next 60 days, it sets the number of days to -1.

Once these two variables have been calculated, they are used to update the state of my recycling_bin_countdown and garden_bin_countdown sensors, which can have the state “Tomorrow” if the number of days is equal to 1, for example.

I can run the calendar.get_events action in Developer Tools:

and the response is the following:

calendar.bin_collections:
  events:
    - start: "2026-01-06"
      end: "2026-01-07"
      summary: Recycling bin collection
      description: ""
    - start: "2026-01-20"
      end: "2026-01-21"
      summary: Recycling bin collection
      description: ""

This works correctly - in this case, there are two recycling bin collections within 60 days in my calendar, but NO garden bins, so that one is absent from the response.

I can then use the “Copy to clipboard as template” button to check everything works in the Template Editor using the following full code:

{% set agenda = {"calendar.bin_collections":{"events":[{"start":"2026-01-06","end":"2026-01-07","summary":"Recycling bin collection","description":""},{"start":"2026-01-20","end":"2026-01-21","summary":"Recycling bin collection","description":""}]}} %}
{% set events = agenda['calendar.bin_collections']['events'] %}

{% set match = events
  | selectattr('summary', 'search', 'Recycling bin collection')
  | map(attribute='start')
  | map('as_datetime')
  | list %}
{% set days_recycling = (match[0] | as_local - today_at()).days if match | length > 0 else -1 %}

{% set match = events
  | selectattr('summary', 'search', 'Garden bin collection')
  | map(attribute='start')
  | map('as_datetime')
  | list %}
{% set days_garden = (match[0] | as_local - today_at()).days if match | length > 0 else -1 %}

days_recycling = {{ days_recycling }}
days_garden = {{ days_garden }}

{% if days_recycling == -1 %}
None upcoming
{% elif days_recycling == 0 %}
Today
{% elif days_recycling == 1 %}
Tomorrow
{% else %}
In {{ days_recycling }} Days
{% endif %}

{% if days_garden == -1 %}
None upcoming
{% elif days_garden == 0 %}
Today
{% elif days_garden == 1 %}
Tomorrow
{% else %}
In {{ days_garden }} Days
{% endif %}

You can see this all works as expected, and returns “None upcoming” for the garden bin:

The Problem

It works correctly when a bin has an upcoming collection:

But fails when there is no upcoming collection, and gets the state “unknown” instead of “None upcoming”:

Anyone spot what’s going on here?

My feeling is that the logic is correct (because it’s returning -1 correctly in template editor), but it’s something to do with assigning variables in the YAML and then trying to use them in the trigger-based template sensor… Although it’s partly obtaining the variables correctly because I indeed obtain “In 26 Days” for my recycling bin…


  • Installation method Home Assistant OS
  • Core 2025.11.3
  • Supervisor 2025.12.3
  • Operating System 16.3
  • Frontend 20251105.1

I tested a slightly modified version of your Trigger-based Template Sensor. The modifications were minimal and only serve to make it work on my system. Basically they are “housekeeping” changes that don’t impact the template’s behavior.

  • It uses an Event Trigger with a custom event (test_event_1) so I can conveniently trigger it on demand for testing purposes.

  • I replaced the calendar with what I have on my system (calendar.testing, a Local Calendar). It does not contain any scheduled recycling or garden collection events.

  • I removed the unique_id option because I don’t want these two sensors recorded in my entity registry.

  • I updated the YAML syntax (trigger:triggers:, platform:trigger:).

  • The test was performed using the latest available version of Home Assistant (2025.12.2).

Click to reveal YAML code
  - triggers:
      - trigger: event
        event_type:
          - test_event_1
    action:
      - action: calendar.get_events
        data:
          start_date_time: "{{ today_at() }}"
          duration:
            days: 60
        target:
          entity_id: calendar.testing
        response_variable: agenda
      - variables:
          events: "{{ agenda['calendar.testing']['events'] }}"
          days_recycling: >-
            {% set match = events
              | selectattr('summary', 'search', 'Recycling bin collection')
              | map(attribute='start')
              | map('as_datetime')
              | list %}
            {{ (match[0] | as_local - today_at()).days if match | length > 0 else -1 }}
          days_garden: >-
            {% set match = events
              | selectattr('summary', 'search', 'Garden bin collection')
              | map(attribute='start')
              | map('as_datetime')
              | list %}
            {{ (match[0] | as_local - today_at()).days if match | length > 0 else -1 }}
    sensor:
      - name: "Recycling bin countdown"
        icon: mdi:trash-can
        state: >
          {% if days_recycling == -1 %}
            None upcoming
          {% elif days_recycling == 0 %}
            Today
          {% elif days_recycling == 1 %}
            Tomorrow
          {% else %}
            In {{ days_recycling }} Days
          {% endif %}
      - name: "Garden bin countdown"
        icon: mdi:trash-can
        state: >
          {% if days_garden == -1 %}
            None upcoming
          {% elif days_garden == 0 %}
            Today
          {% elif days_garden == 1 %}
            Tomorrow
          {% else %}
            In {{ days_garden }} Days
          {% endif %}

Testing Results

  • On initial loading, both sensors reported unknown which was expected because they had not been triggered yet.

  • Using Developer Tools → Events, I fired test_event_1 and it served to trigger the sensors.

  • Both sensors reported None upcoming.

In calendar.testing, I scheduled a “Garden bin collection” event for next week, fired trigger_event_1 to trigger the sensors and they reported the following:

The conclusion is that I cannot reproduce the error you are experiencing on my system. I suggest you consider upgrading to the latest version. It may not help but at least your tests will be based on the same underlying software code.


EDIT

Let me know if you want me to perform any other kind of tests on these sensors.

Thanks, just a quick check: can you also run the same test but use the home assistant start as the trigger, same as me? Instead of using a seperate event to trigger it?

I wonder if it is something with the order that things are evaluated when home assistant is restarted…

  • sensor.garden_bin_countdown initially reports In 7 days.
  • Added the startup trigger.
  • Reloaded Template entities.
  • Deleted the scheduled garden bin event from calendar.testing.
  • Restarted Home Assistant
  • sensor.garden_bin_countdown now reports None upcoming.

On my system, the sensor’s behavior on startup is the same as when I fire the custom event.

Thanks for testing. I have upgraded to 2025.12.2 same as you, but seeing the same “unknown” state for an entity that does not have a calendar entry.

This is strange…

As an experiment, add the Event Trigger, that I had used (see code above), to your sensor configuration.

Reload Template Entities then go to Developer Tools → Events and fire the custom event test_event_1 and then check the sensor’s state.

If it continues to report unknown then I suggest a ‘scorched earth’ approach. Delete both sensors (from the file and then via the UI in Settings → Devices & Services → Entities), restart Home Assistant and then re-enter the sensor configuration. Use different values for the unique_id to ensure there’s no chance of overlap with any previous record of operation.


EDIT

By “record of operation” I mean that Home Assistant maintains an internal record in files located within the hidden .storage folder.

core.restore_state
homeassistant.exposed_entities
core.entity_registry

I have done as you have suggested:

  1. Fired a custom event test_event_1 instead
  2. Completely removed the code from the configuration.yaml, deleted the entities manually in Settings, re-added the yaml code but with different entity IDs.

Both still result in “Unknown”

Interestingly, I have another, older system, which works correctly:

That system is running the following:

  • Installation method Home Assistant OS
  • Core 2025.5.3
  • Supervisor 2025.12.3
  • Operating System 15.2
  • Frontend 20250516.0

Then you’re in a better position to compare the two systems and attempt to determine why it works on one but not the other.

I can’t replicate the problem; your Trigger-based Template Sensors work correctly on my system. Without the ability to cause the problem, I can’t experiment to determine how to eliminate it.


FWIW, normally I would suggest reporting it as an Issue in Home Assistant’s Github Core repository. However, whomever attends to it must first be able to reproduce the problem. If it can’t be reproduced, they will be in the same position as me, unable to perform tests to fix it.

If you do choose to report it, I advise you to create the simplest possible example that demonstrates the problem.


EDIT

When a Trigger-based Template Sensor reports unknown it is normally due to it not having been triggered yet. In other words, it has never evaluated its template so it has nothing to report.

If its state value remains unknown no matter how many times it has been triggered then there’s a missing piece to this puzzle.

Okay thanks for doing the tests on your system.

I agree, and this is what I initially thought. But it’s odd then that the other Recycling bin is correctly getting its state - they are both triggered by the same thing…

The only way it can fail, that I can think of, is if there’s a misconfiguration and the Garden Bin sensor is handled as a separate Template Sensor entity (i.e. not a Trigger-based Template Sensor). In that situation, its template would never be evaluated (because it contains nothing that changes state) and it would permanently report unknown.

However, the example you posted doesn’t appear to be misconfigured. I used the same structure in my test configuration (two sensors defined directly under a common set of triggers) and both are triggered (and both work).

My guess is that this will error out because there is no match[0].
The if statement does not short circuit to prevent it. Either use a full if else or a get method with a default.

As a result, the days is not set, causing problems later on.

Interesting. This was the reason for the “if match” logic, but you are saying it might not be sufficient?

Can you provide a full replacement for this line, for me to test?

Thanks

match[0] is used only if the length of the match list is greater than 0.

If for some reason it attempted to reference a non-existent list item, it would report an error (in the Log).

No, not true. It is evaluated before length is checked. Length does not get checked because of the error.

{% set days_garden = -1 %}
{% if match | length > 0 %}
  {% set days_garden = (match[0] | as_local - today_at()).days %}
{% endif %}

There’s no functional difference between that and an inline if statement.

You may be thinking of an Immediate If statement. Its if_true and if_false terms are always evaluated regardless of whether the condition is true or false.

I was under the impression it applies to both.

No just an Immediate If.

You can prove it for yourself with this example.

{% set match = [] %}

{{ match[0] if match | length > 0 else -1 }}

It reports -1


EDIT

Review the Warning section of the documentation for Immediate If. It explains how those two forms of if behave differently.

1 Like

I seem to recall being mentioned the template checker was more lenient with regard to some errors. I may very well be wrong, but it does not hurt to try.

Also why is it then working on Taras’ system, and on my old system? Clearly the match[0] must be working to some extent?