Skip to content

Unsupported IOT.IPCAMERA devices raise a bare KeyError from get_device_class_from_sys_info during discovery (fix written in #1571, closed by stale bot) #1753

Description

@daj1120

Summary

A Kasa camera/doorbell that answers legacy discovery on UDP/9999 causes
get_device_class_from_sys_info to raise a bare KeyError, which escapes
Discover.datagram_received entirely and surfaces as an unhandled asyncio callback
exception in the consuming application.

This is the library-side cause of home-assistant/core#138866 (open since 2025-02-19,
labelled waiting-for-upstream).

This is not a request for camera support — #467 already tracks that. This is only a
request that an unsupported device type fail the way the library's own callers already
expect it to fail.

Reproduction

python-kasa 0.10.2, Python 3.14.

Any device reporting "type": "IOT.IPCAMERA" in its legacy get_sysinfo response. Here
it is a Kasa KD110(US) video doorbell, hw 4.0, fw 2.3.26 Build 20240508. Three of
them on the network produce three tracebacks per discovery run, indefinitely.

  File "kasa/discover.py", line 377, in datagram_received
    device = device_func(info, config)
  File "kasa/discover.py", line 742, in _get_device_instance_legacy
    device_class = cast(type[IotDevice], Discover._get_device_class(info))
  File "kasa/discover.py", line 722, in _get_device_class
    return get_device_class_from_sys_info(info)
  File "kasa/device_factory.py", line 145, in get_device_class_from_sys_info
    return TYPE_TO_CLASS[IotDevice._get_device_type_from_sys_info(sysinfo)]
KeyError: <DeviceType.Camera: 'camera'>

Cause

kasa/device_factory.py:135-145 — DeviceType.Camera was commented out of
TYPE_TO_CLASS in #1480 ("Disable iot camera creation until more complete", merged
2025-01-25), but the lookup remained a bare subscript:

    TYPE_TO_CLASS = {
        ...
        # Disabled until properly implemented
        # DeviceType.Camera: IotCamera,
    }
    return TYPE_TO_CLASS[IotDevice._get_device_type_from_sys_info(sysinfo)]

_get_device_type_from_sys_info still maps IOT.IPCAMERA to DeviceType.Camera, so the
subscript raises KeyError.

datagram_received guards only UnsupportedDeviceError (discover.py:378) and
KasaException (:385). KeyError is neither, so it propagates out of the protocol
callback. Because the raise is at :377, the code at :391-394 that records the device
and invokes on_discovered never runs — so downstream consumers cannot even see, filter
or ignore the device.

The fix already exists

#1571 ("Raise UnsupportedDeviceError for unsupported legacy device types", @rytilahti,
2025-08-31) does exactly this, and adds the fixture
incomplete_iotcamera = _make_unsupported("IOT.IPCAMERA", "XOR").

It was stale-labelled 2025-11-30 and auto-closed 2025-12-08 with no human review.
kasa/device_factory.py is byte-identical between 0.10.2 and master today.

Its author flagged one concern in the description — "The test might not be correct, as
this was also raising even before adding the new raise, needs to be verified."
— which
looks like the only thing standing between it and merge.

Impact

Downstream (Home Assistant) this produces a 19-line traceback per responding camera per
15-minute discovery cycle, indefinitely, for devices the user has deliberately chosen not
to integrate. On my instance that was ~288 tracebacks/day and about 94% of the retained
log file
— it evicts unrelated evidence, which is how I found it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions