RecursionError: maximum recursion depth exceeded in comparison

I have a custom authored component that seems to be causing this issue sometimes:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/aiohttp/web_protocol.py", line 410, in start
    resp = yield from self._request_handler(request)
  File "/usr/local/lib/python3.6/site-packages/aiohttp/web.py", line 325, in _handle
    resp = yield from handler(request)
  File "/usr/local/lib/python3.6/site-packages/aiohttp/web_middlewares.py", line 93, in impl
    return (yield from handler(request))
  File "/usr/src/app/homeassistant/components/http/ban.py", line 58, in ban_middleware
    return (yield from handler(request))
  File "/usr/local/lib/python3.6/asyncio/coroutines.py", line 215, in coro
    res = yield from res
  File "/usr/local/lib/python3.6/asyncio/coroutines.py", line 215, in coro
    res = yield from res
  File "/usr/src/app/homeassistant/components/http/__init__.py", line 430, in handle
    result = yield from result
  File "/config/custom_components/wirelesstags.py", line 67, in post
    yield from self._set_state_if(name + '_temp', temperature)
  File "/usr/local/lib/python3.6/asyncio/coroutines.py", line 212, in coro
    res = func(*args, **kw)
  File "/config/custom_components/wirelesstags.py", line 45, in _set_state_if
    self._hass.states.async_set(entity, new_state, attributes=attributes)
  File "/usr/src/app/homeassistant/core.py", line 739, in async_set
    same_attr = is_existing and old_state.attributes == attributes
RecursionError: maximum recursion depth exceeded in comparison

The component is a very small component that is a custom HomeAssistantView. I have about 10 temperature/humidity tags that call it. Each call it sends the temp/humidity and battery. In the View, I take the post and I update 3 individual sensors.

The sensors are custom. They are just gutted template sensors. I took a template sensor and removed the template value rendering.

I will always get this error, but it can run for hours before the error happens. I don’t know if maybe a sensor is firing back to back calls and one is tripping over the other or what.

I cleared out the logs and restarted HA last night about 8 hours ago and I haven’t gotten the error. But, I’m about 90% sure that I’ll have the error many times before I get home from work today.

The meat of the custom component:

@asyncio.coroutine
def _set_state_if(self, entity, new_state):

    state = self._hass.states.get(entity)
    attributes = state.attributes if state else None

    self._hass.states.async_set(entity, new_state, attributes=attributes)

@asyncio.coroutine
def post(self, request):
    """Accept the POST from the wirelesstag manager."""

    data = None

    try:
        data = yield from request.json()
    except ValueError:
        return self.json_message('Invalid JSON', HTTP_BAD_REQUEST)

    if data:

        # Base sensor name
        name = 'sensor.' + data[0]

        temperature = str(data[1])
        humidity = str(data[2])
        battery_volt = str(data[3])

        yield from self._set_state_if(name + '_temp', temperature)
        yield from self._set_state_if(name + '_humidity', humidity)
        yield from self._set_state_if(name + '_battery', battery_volt)

    return self.json({})

Today I received the same error from this simple script I was using to force-write switch state into DB. The script is run by automation every 5 minutes. Just one entity is processed in that way:

#pass entity_id as argument from call
sensor = data.get('entity_id')

#read old state
oldstate = hass.states.get(sensor)

#write old state to entity and force update to record database
hass.states.set(sensor, oldstate.state , oldstate.attributes, force_update=True)

(it really doesn’t get much simpler than that…)

The problem is the same as in your case - it can work OK for hours before this happens. Didn’t have time yet to check it thoroughly, but I thought that it’s worth mentioning that you’re not alone there.

Today I faced the same problem as yours, with exactly same small script, which I also use to force update “slow” sensors.