Skip to content

fix: drop non-UTF-8 cloud mips message instead of crashing mqtt loop#1750

Open
Heartcoolman wants to merge 1 commit into
XiaoMi:mainfrom
Heartcoolman:fix-non-utf8-mips-payload
Open

fix: drop non-UTF-8 cloud mips message instead of crashing mqtt loop#1750
Heartcoolman wants to merge 1 commit into
XiaoMi:mainfrom
Heartcoolman:fix-non-utf8-mips-payload

Conversation

@Heartcoolman

Copy link
Copy Markdown

Problem

Fixes #1749.

MipsCloudClient._on_mips_message decodes every cloud push with a bare payload.decode('utf-8') (miot_mips.py:1104). Some cloud pushes carry payloads that are not valid UTF-8 — on my instance this fired 19 times in 8 days (offending byte always around position 162–190, e.g. 0xaa, 0x80, 0xee), each time raising UnicodeDecodeError inside paho's on_message:

File "/config/custom_components/xiaomi_home/miot/miot_mips.py", line 1104, in _on_mips_message
    payload_str: str = payload.decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xee in position 168: invalid continuation byte

The exception aborts paho's read loop (__mqtt_loop_handler re-raises) and the message is lost. When a lost push is a device online/offline state notification, the device's entities stay unavailable in HA indefinitely — in my case a linp.light.lx2bcw was stuck for ~17 hours while working fine in the Mi Home app, and reloading the config entry restored it instantly. Full logs in #1749.

Change

Catch UnicodeDecodeError in MipsCloudClient._on_mips_message, log the topic and the payload hex (so the actual encoding of these messages can be diagnosed from user reports), and skip the message. One malformed push can no longer abort MQTT message processing.

The failing byte offsets (160+ bytes decode fine, then an invalid byte) suggest mostly-JSON text with an embedded non-UTF-8 sequence rather than a packed/TLV message, so no alternative decode path is attempted — the message is dropped defensively.

Testing

  • Standalone unit exercise of _on_mips_message (duck-typed client):
    • valid UTF-8 payload → handler dispatched with decoded string (unchanged behavior);
    • non-UTF-8 payload (byte pattern from production logs) → no exception, one log_error, handler not called;
    • no-subscriber early-return path unaffected.
  • pylint --rcfile=.pylintrc on the file: 10.00/10 (same as before the change).
  • test/test_mips.py requires live cloud credentials/gateway, not run.

MipsCloudClient._on_mips_message decodes the push payload with a bare
payload.decode('utf-8'). Some cloud pushes carry payloads that are not
valid UTF-8, which raises UnicodeDecodeError inside paho's on_message,
aborts the read loop and silently drops the message. Lost device
online/offline pushes can leave a device stuck unavailable until the
config entry is reloaded manually.

Catch UnicodeDecodeError, log the topic and the payload hex for
diagnosis, and skip the message so that one malformed push cannot
break message processing.

Related to XiaoMi#1749
@CLAassistant

CLAassistant commented Jul 7, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cloud MIPS client: UnicodeDecodeError on non-UTF-8 push payload (miot_mips.py:1104); dropped pushes leave device stuck unavailable until reload

2 participants