Hi HA community,
My HA version is 2026.9.3
Setup:
I have a binary_sensor Group helper (binary_sensor.security_openings_away) whose members are themselves other Group helpers, each wrapping a single physical door/window contact sensor — so it’s a group-of-groups, 8 direct members, ~20 leaf sensors once fully expanded. This entity is used by a script that sends an intrusion report by e-mail when the alarm triggers.
Symptom:
When I compute expand('binary_sensor.security_openings_away') | list inside a top-level variables: step of the script (see Script A below), the resulting count is wildly inflated and inconsistent between runs — I saw 2032 and, a bit later with no change to the group itself, 3503. The true member count (confirmed repeatedly via Developer Tools > Template, checked every ~30-60s with nothing changing) is stable at 8 direct / ~20 expanded.
When I take the exact same expand() expression and compute it inline inside the data.message (or data.html) field of the notify.send_message action itself, instead of in a separate variables: step (Script B below), it reliably returns the correct, stable count every single time.
What I ruled out:
- Group instability / something else modifying the group over time: checked the direct member count repeatedly over several minutes with nothing triggering — stayed at 8 the whole time.
- Timing/delay: tested with both a 12s and a ~1s delay before the scan, same discrepancy each time (variables: block wrong, inline correct).
- Nested-group support in
expand(): the official docs state it resolves nested groups recursively, and it clearly does — just not consistently when the call sits invariables:on my install.
Minimal reproduction, two versions below — only difference is where the expand() calls live.
Script A (variables: block — broken on my install):
# Version A — "conventional" placement
# expand() is computed once in a top-level "variables:" step, then reused
# in the notify service call.
# => On my instance, this returned wildly inflated / inconsistent counts
# (e.g. 2032, then 3503 on a later run) for a group that only has
# 8 direct members and ~20 entities once nested groups are expanded.
alias: Alarm report - variables block version
sequence:
- delay: "00:00:05"
- variables:
openings_total: "{{ expand('binary_sensor.security_openings_away') | list }}"
openings_on: >
{{ openings_total | selectattr('state','eq','on') | list }}
- action: notify.send_message
target:
entity_id: notify.email_home
data:
title: "Alarm triggered"
message: >
{{ openings_on | count }} opening(s) currently open,
out of {{ openings_total | count }} total members.
mode: single
Script B (inline in the service call’s data — works correctly):
# Version B — "inline" placement
# The exact same expand() expression, computed inside the notify service
# call's own data field instead of a separate "variables:" step.
# => On my instance, this reliably returns the correct, stable count
# every time (matches the true membership of the group).
alias: Alarm report - inline in service data version
sequence:
- delay: "00:00:05"
- action: notify.send_message
target:
entity_id: notify.email_home
data:
title: "Alarm triggered"
message: >
{% set openings_total = expand('binary_sensor.security_openings_away') | list %}
{% set openings_on = openings_total | selectattr('state','eq','on') | list %}
{{ openings_on | count }} opening(s) currently open,
out of {{ openings_total | count }} total members.
mode: single
Question for the community: has anyone run into this before? Is this a known quirk/bug with how variables: renders templates that return lists of State objects from expand(), particularly with nested groups? I couldn’t find an existing issue describing this specific combination. Happy to file one if this isn’t already known — pointers to relevant source/discussion welcome in the meantime.