Need help understanding why a template is generating a loop error

I’m trying to understand a warning in the logs.

I have a template sensor that sums up values every time a dependent state changes.

- sensor:
    - name: Total House Gallons
      unique_id: droplet_total_house_gallons
      unit_of_measurement: "gal"
      device_class: water
      state_class: total
      state: >
        {{ states('sensor.droplet_e67c_water')|float(0) + this.state|float(0) }}

But this generates a template loop warning, and I’m not seeing why. It’s not like the sensor is using something like a template that includes ALL (including itself) sensors:

{{ states.sensor| ... .

Could it be it’s somehow self-referencing with this.state?

I thought the template sensors only watched the explicit sensors listed.

2025-10-15 14:13:09.208 WARNING (MainThread) [homeassistant.components.template.template_entity] Template loop detected while processing event: <Event state_changed[L]: entity_id=sensor.total_house_gallons, old_state=<state sensor.total_house_gallons=-0.00878372074090844; state_class=total_increasing, unit_of_measurement=gal, device_class=water, friendly_name=Total House Gallons @ 2025-10-15T14:13:09.205775-07:00>, new_state=<state sensor.total_house_gallons=-0.00839538782394196; state_class=total_increasing, unit_of_measurement=gal, device_class=water, friendly_name=Total House Gallons @ 2025-10-15T14:13:09.207246-07:00>>, skipping template render for Template[{{ states('sensor.droplet_e67c_water')|float(0) + this.state|float(0) }}]

I solved it by adding an explicit trigger, but what was triggering the loop w/o the trigger?

  triggers:
    - trigger: state
      entity_id: sensor.droplet_e67c_water

BTW, I’m using device_class total instead of total_increasing because the sensor can report a negative value. I guess water can flow uphill…

The volume reported by Droplet over local API is point-to-point, meaning that each new value represents the difference in volume recorded since this data was last sent.

This device also reports a flow rate in g/m. How does using the integration sensor platform differ from just adding up as above?

- platform: integration
  source: sensor.droplet_e67c_flow_rate
  name: "Flow-based Total Water Usage"
  round: 2
  unit_time: min
  method: left

Thanks,

The sensor doesn’t make sense without a trigger. You’re telling Home Assistant to direct all of its resources to keep accumulating the value of sensor.droplet_e67c_water, so the computation of the state is guaranteed never to complete. I assume the implementation is smart enough to go with 0 (the default value you pass to float), but it’s giving you the warning because the code is non-sensical.

With a trigger, you’re telling Home Assistant to do the accumulation each time the state of the sensor changes. So there it’s still going to go with 0 for this.state if a state doesn’t exist, but at least it knows that it’s accumulating based on some specific trigger.

Is that correct? Isn’t that saying to update the template sensor whenever sensor.droplet_e67c_water changes?

I have a lot of templates that don’t have triggers. The state-based template docs say

Template entities will by default update as soon as any of the referenced data in the template updates.

Coudn’t you have a template that simply doubles the value w/o adding a trigger and just updates whenever that entity’s state changes? I just tested this and it doesn’t generate any loop warnings.

- sensor:
    - name: test double gals
      unique_id: test_double_gals
      unit_of_measurement: "gal"
      device_class: water
      state_class: total
      state: >
        {{ states('sensor.droplet_e67c_water')|float(0) * 2 }}

Make me think that this.state is triggering the self referencing warning.

But your template sensor’s state is depends on itself, right? So as soon as you add the value of sensor.droplet_e67c_water, the template sensor has to update again. That’s an (implicit) infinite loop.

You don’t have that problem when you add the trigger. When the trigger fires, a snapshot is taken of this.state, the state updates, and then it waits for another change on sensor.droplet_e67c_water.

Yes, see this post: Count substring occurences inside a string returned from sensor - #22 by petro and this post: Count substring occurences inside a string returned from sensor - #24 by petro

Oh. I see my mistake. I was thinking the implicit trigger was just looking at state changes in sensor.droplet_e67c_water – i.e. somehow just parsing out the entity name. But, no, it’s looking at the entire template

{{ states('sensor.droplet_e67c_water')|float(0) + this.state|float(0) }}

So, when the template sensor is updated this.state changes and then the entire template changes state, and triggers it again.

Is that correct?

There’s another problem in my template, I think. The device reports volume of water since the last update. With a constant flow it’s possible that the device could report exactly the same amount as previously reported. In that case there won’t be a state change and thus the template wouldn’t get updated.

Ugh, so my post crossed with yours. Looks like it is the this.state

IIRC, if you omit availability, it should only resolve once but I could be wrong on that. It’s been a while since I’ve looked at that portion of the code. I do know it’s unavoidable unless the system is overhauled, which I’m not willing to do.

I just tried this using an input_number and yes, it did add things twice, even w/o availability in the config.

A far easier way to do this would be to use the Utility Meter with the Delta Values option set to true.

Ok, I’ll try the utility meter. Maybe it’s not important, but was going for a total value like my water meter, but resetting monthly isn’t really a problem.

utility_meter:
  house_water_usage_month:
    unique_id: house_water_usage_month
    source: sensor.droplet_e67c_water
    net_consumption: true
    delta_values: true
    always_available: true
    cycle: monthly

Will that have the same problem if the device reports the same volume as previously?

The sensor reports in milliliters so maybe unlikely to get the same update twice in a row. The volume_delta is the entity above.

Droplet updated: flow=0.0,volume_delta=28.54,server_connectivity=connected,signal_quality=strong_signal
Droplet updated: flow=0.0,volume_delta=10.88,server_connectivity=connected,signal_quality=strong_signal
Droplet updated: flow=0.0,volume_delta=-14.11,server_connectivity=connected,signal_quality=strong_signal
Droplet updated: flow=0.0,volume_delta=-22.1,server_connectivity=connected,signal_quality=strong_signal
Droplet updated: flow=0.0,volume_delta=-7.44,server_connectivity=connected,signal_quality=strong_signal
Droplet updated: flow=0.0,volume_delta=16.22,server_connectivity=connected,signal_quality=strong_signal

Sensor is updated like this, it seems. It’s converted to liters.

DropletSensorEntityDescription(
        key=KEY_VOLUME,
        device_class=SensorDeviceClass.WATER,
        native_unit_of_measurement=UnitOfVolume.LITERS,
        suggested_unit_of_measurement=UnitOfVolume.GALLONS,
        suggested_display_precision=2,
        state_class=SensorStateClass.TOTAL,
        value_fn=lambda device: device.get_volume_delta() / ML_L_CONVERSION,
        last_reset_fn=lambda device: device.get_volume_last_fetched(),
    ),

BTW – just noticed if changing from gallons to liters it seems the states table uses whatever the display unit of measurement is at the time. Mixed values in the table. Interesting.

Then don’t include a reset cycle. Then it will never reset.

Don’t know for sure but don’t think so.