TypeError: unsupported operand type(s) for -: 'float' and 'str' when using template sensor

Hi, I have pasted the error and code below. It worked fine before upgrading from 0.79.3 to 0.84.6. I think the error appeared before upgrading, but after that the sensor started fine, so it was no real problem. Now my ventilation runs all the time…

Update for sensor.bathroom_hallway_humidity_difference_highpass fails
Traceback (most recent call last):
  File "/usr/src/app/homeassistant/helpers/entity.py", line 221, in async_update_ha_state
    await self.async_device_update()
  File "/usr/src/app/homeassistant/helpers/entity.py", line 347, in async_device_update
    await self.async_update()
  File "/usr/src/app/homeassistant/components/sensor/template.py", line 196, in async_update
    self._state = self._template.async_render()
  File "/usr/src/app/homeassistant/helpers/template.py", line 138, in async_render
    return self._compiled.render(kwargs).strip()
  File "/usr/local/lib/python3.6/site-packages/jinja2/asyncsupport.py", line 76, in render
    return original_render(self, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 1008, in render
    return self.environment.handle_exception(exc_info, True)
  File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 780, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 1, in top-level template code
TypeError: unsupported operand type(s) for -: 'float' and 'str'

sensor:
  - platform: template
    sensors:
      bathroom_hallway_humidity_difference:
        friendly_name: Bathroom-Hallway Humidity Difference
        unit_of_measurement: '%'
        value_template: "{{ float(states('sensor.bathroom_multisensor_relative_humidity')) - float(states('sensor.hallway_multisensor_relative_humidity')) }}"
  - platform: filter
    name: Bathroom-Hallway Humidity Difference Average
    entity_id: sensor.bathroom_hallway_humidity_difference
    filters:
      - filter: lowpass
        time_constant: 10
        precision: 1
  - platform: template
    sensors:
      bathroom_hallway_humidity_difference_highpass:
        friendly_name: Bathroom-Hallway Humidity Difference Highpass
        unit_of_measurement: '%'
        value_template: "{{ float(states('sensor.bathroom_hallway_humidity_difference')) - float(states('sensor.bathroomhallway_humidity_difference_average')) }}"
1 Like

The float function, when passed a string that cannot be interpreted as a floating point number, returns the string. You should use the float filter instead, which returns zero (by default) when it can’t interpret a string.

BTW, my guess is that you either have a typo in the entity_id’s, or the entity doesn’t exist at some point (possibly right after startup), in which case the states function is probably returning ‘unknown’, which, of course, cannot be interpreted as a floating point number.

So, change:

        value_template: "{{ float(states('sensor.bathroom_hallway_humidity_difference')) - float(states('sensor.bathroomhallway_humidity_difference_average')) }}"

to:

        value_template: "{{ states('sensor.bathroom_hallway_humidity_difference')|float - states('sensor.bathroomhallway_humidity_difference_average')|float }}"
3 Likes

Thank you very much! I actually checked float in jinja2 docs, and assumed that what I did should work as described there. So, is “function style” actually Python semantics, and “filter style” jinja?

The Jinja implementation in HA (at least based on observation) is a mixture of Jinja and Python. A lot of what I’ve done in Jinja templating is actually Python. I’m not 100% sure when you do float(x) if that is directly calling Python’s float function, or if there’s a bit of a wrapper around it. E.g., float('unknown') in Python throws an exception, whereas in Jinja it simply returns the string 'unknown'. The Jinja float filter – |float(default) – however behaves differently when the “input” can’t be converted – it returns the default, and the “default” default is 0.0. I wouldn’t be surprised that, “under the covers”, the implementation of the float filter also uses Python’s float function. Clear as mud? :wink:

1 Like