core: Exception since 2023.5.0: state class None: numeric value, however, it has the non-numeric value

The problem

Referring to https://github.com/home-assistant/core/issues/92483 this is a general problem esp. for template sensors since 2023.5.0.

Can anyone or the one who implemented this error message (was it you @epenet in https://github.com/home-assistant/core/pull/85605?) please give one single example how to define now a template sensor with a number state class or a uom and which is working without error at system start?

What I tried already: As a trigger template should restore it’s state at startup, then I tried to set a change trigger on the source, which is perhaps not available on startup of the template and a trigger on ha-start and a if with is_number, so that the template should either take his old (or restored value) number value or the/a new number value from source. But it returns the same error on startup for whatever reasons because it should work, at least think so.

What version of Home Assistant Core has the issue?

= core-2023.5.0

What was the last working version of Home Assistant Core?

core-2023.4.x

What type of installation are you running?

Home Assistant OS

Integration causing the issue

sensor

Link to integration documentation on our website

https://www.home-assistant.io/integrations/sensor/

Diagnostics information

No response

Example YAML snippet

Already tried this. But this as trigger sensor (to restore state) or as a standard sensor, it gives the error message at startup. Here example for maximum sensor, but minimum (and a lot of other sensors, which relies on available sensors, which are perhaps at this point of time not yet available at startup) is havin same problem.



  - trigger:
      - platform: state
        entity_id: sensor.aussenthermometer_max_letzte_24_stunden
      - platform: homeassistant
        event: start
      - platform: event
        event_type: event_template_reloaded
  - sensor:
      - name: Außenthermometer Maximum
        unique_id: unique_id_template_sensor_aussenthermometer_maximum
        state: >
          {% if is_number(states('sensor.aussenthermometer_max_letzte_24_stunden')) %}
            {{ states('sensor.aussenthermometer_max_letzte_24_stunden') }}
          {% else %}
            {{ states('sensor.aussenthermometer_maximum') }}
          {% endif %}
        icon: mdi:thermometer-plus
        device_class: temperature
        state_class: measurement
        unit_of_measurement: "°C"
        attributes:
          zeit: >
            {{ states('sensor.aussenthermometer_max_letzte_24_stunden_zeit') }}


### Anything in the logs that might be useful for us?

```txt
2023-05-23 08:03:13.370 ERROR (MainThread) [homeassistant] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 579, in state
numerical_value = int(value)
ValueError: invalid literal for int() with base 10: 'unknown'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/template_entity.py", line 379, in _async_template_startup
result_info.async_refresh()
File "/usr/src/homeassistant/homeassistant/helpers/event.py", line 953, in async_refresh
self._refresh(None)
File "/usr/src/homeassistant/homeassistant/helpers/event.py", line 1133, in _refresh
self.hass.async_run_hass_job(self._job, event, updates)
File "/usr/src/homeassistant/homeassistant/core.py", line 607, in async_run_hass_job
hassjob.target(*args)
File "/usr/src/homeassistant/homeassistant/helpers/template_entity.py", line 348, in _handle_results
self.async_write_ha_state()
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 585, in async_write_ha_state
self._async_write_ha_state()
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 649, in _async_write_ha_state
state = self._stringify_state(available)
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 591, in _stringify_state
if (state := self.state) is None:
File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 583, in state
raise ValueError(
ValueError: Sensor sensor.aussenthermometer_maximum has device class temperature, state class measurement unit °C and suggested precision None thus indicating it has a numeric value; however, it has the non-numeric value: unknown (<class 'str'>)
2023-05-23 08:03:13.415 ERROR (MainThread) [homeassistant] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 579, in state
numerical_value = int(value)
ValueError: invalid literal for int() with base 10: 'unknown'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/template_entity.py", line 379, in _async_template_startup
result_info.async_refresh()
File "/usr/src/homeassistant/homeassistant/helpers/event.py", line 953, in async_refresh
self._refresh(None)
File "/usr/src/homeassistant/homeassistant/helpers/event.py", line 1133, in _refresh
self.hass.async_run_hass_job(self._job, event, updates)
File "/usr/src/homeassistant/homeassistant/core.py", line 607, in async_run_hass_job
hassjob.target(*args)
File "/usr/src/homeassistant/homeassistant/helpers/template_entity.py", line 348, in _handle_results
self.async_write_ha_state()
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 585, in async_write_ha_state
self._async_write_ha_state()
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 649, in _async_write_ha_state
state = self._stringify_state(available)
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 591, in _stringify_state
if (state := self.state) is None:
File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 583, in state
raise ValueError(
ValueError: Sensor sensor.aussenthermometer_minimum has device class temperature, state class measurement unit °C and suggested precision None thus indicating it has a numeric value; however, it has the non-numeric value: unknown (<class 'str'>)
2023-05-23 08:03:14.770 ERROR (MainThread) [homeassistant.helpers.event] Error while processing state change for sensor.aussenthermometer_min_letzte_24_stunden_zeit
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 579, in state
numerical_value = int(value)
ValueError: invalid literal for int() with base 10: 'unknown'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/event.py", line 287, in _async_state_change_dispatcher
hass.async_run_hass_job(job, event)
File "/usr/src/homeassistant/homeassistant/core.py", line 607, in async_run_hass_job
hassjob.target(*args)
File "/usr/src/homeassistant/homeassistant/helpers/event.py", line 1133, in _refresh
self.hass.async_run_hass_job(self._job, event, updates)
File "/usr/src/homeassistant/homeassistant/core.py", line 607, in async_run_hass_job
hassjob.target(*args)
File "/usr/src/homeassistant/homeassistant/helpers/template_entity.py", line 348, in _handle_results
self.async_write_ha_state()
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 585, in async_write_ha_state
self._async_write_ha_state()
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 649, in _async_write_ha_state
state = self._stringify_state(available)
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 591, in _stringify_state
if (state := self.state) is None:
File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 583, in state
raise ValueError(
ValueError: Sensor sensor.aussenthermometer_minimum has device class temperature, state class measurement unit °C and suggested precision None thus indicating it has a numeric value; however, it has the non-numeric value: unknown (<class 'str'>)

Additional information

No response

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 28 (25 by maintainers)

Most upvoted comments

Yes. The above is the trigger sensor.

No, it’s not. The configuration snippet has a template trigger without any entities, followed by a regular (state based) template sensor.

image

why is it not restored

Regular template sensors don’t restore their state.

I am not a integration developer, but interact with home assistant’s states via templates, MQTT, and the SQL database

So you are integrating… as with those integrations you define the data, not Home Assistant. The same rules as any other integration apply.

From my point of view, None as a state is completely foreign concept, it would be the equivalent of the state being an empty string.

That sentence makes no sense. A nil value isn’t equal to an empty string, that makes barely any sense in any program (not just Home Assistant).

The user doesn’t actually encounter a None as a state and the states are always strings.

That is correct, the state of an entity is determined by multiple things, depending on the native state value provided, but also other things (like availability of devices and config entries).

Now they must either use a template and santitize the input via jinja or implement mqtt availability topics. A simple task is now considerably more complex because parsing a string for an error is considered wrong because it’s supposed to be numeric only sensor.

“input” not equals “output”, it seems however, that assumption is made.

The logic for this is bit baffling. For all the effort we gone through home assistant will translate that None into back into unknown. Why can’t we simply declare state as unknown ourselves?

Because the unknown state is a result of not having a state value, yet the entity (and everything above it) is available.

…/Frenck

I think there is a difference on how people view what a home assistant state is. I am not a integration developer, but interact with home assistant’s states via templates, MQTT, and the SQL database. From my point of view, None as a state is completely foreign concept, it would be the equivalent of the state being an empty string. The user doesn’t actually encounter a None as a state and the states are always strings. When the templates started to crash because we returned unknown it was a head scratcher as a regular sensor is supposed to report this as an error state.

For home assistant developers having a None type as a state is completely natural as you think of self._attr_state = None when there is no valid data and coded your templates to return None because that was the python way. But now this has now forcefully moved from the outside scope of the internal python API.

Consider this example sensor

mqtt:
  sensor:
    - state_topic: "home/bedroom/temperature"
    - unit_of_measurement: `°F`

It’s input is essentially text only. You can’t serialize a python None over this interface. Sending an empty string is not the same as none and it won’t work. A user used to be able send ‘unknown’ if their mqtt temperature sensor is in error. Now they must either use a template and santitize the input via jinja or implement mqtt availability topics. A simple task is now considerably more complex because parsing a string for an error is considered wrong because it’s supposed to be numeric only sensor.

The logic for this is bit baffling. For all the effort we gone through home assistant will translate that None into back into unknown. Why can’t we simply declare state as unknown ourselves?

I opened a documentation PR to at least document that the state template needs to render to a number as well as give an example of error handling by adding an availability template.

On a side note, this is a somewhat similar case to when we changed a lot of template functions to not return 0 on error in the sense that it also requires error handling to be added to the templates.

I’ve started to look into this, and the issue is definitely with template integration, not sensor integration.

What I am unsure about is whether it should be resolved globaly or within each template.

One way to resolve would be to adjust: https://github.com/home-assistant/core/blob/657d285e8fe346908a1eb618dd4d987bb3190236/homeassistant/components/template/sensor.py#L229-L231

to have instead

        if isinstance(result, TemplateError) or result == STATE_UNKNOWN:
            self._attr_native_value = None
            return

I don’t know if it would be the best solution. You are welcome to open a PR and see what others think…