Skip to content

ThirdReality Smart Plug Gen3 OTA fail (47 to 56) #1268

Description

@markuswinkler

What happened?

OTA update of a ThirdReality Smart Plug Gen3 (bl702_plug_gen3_usa, hw v1) from firmware 47 to 56 consistently fails with INVALID_IMAGE after the image transfer reaches ~99% complete. The device receives essentially the entire image over Zigbee, then rejects it at the final validation step. This is fully reproducible — every attempt fails the same way.

I have 11 devices of this exact model/hardware revision on my network with the 47 → 56 update pending. I've only attempted the update on one so far (to avoid repeating a failure across all of them), but wanted to flag it before trying the rest.

Log excerpt (Zigbee2MQTT container log):

[2026-08-11 13:47:44] info: z2m:mqtt: ... 'update': {'installed_version':47,'latest_version':56,'progress':98.91,'remaining':17,'state':'updating'} ...
[2026-08-11 13:47:52] error: z2m: OTA update of 'Basement - Dehumidifier - Outlet' failed (OTA update of 0x4ce175b4dc440000 failed with reason: INVALID_IMAGE)
[2026-08-11 13:47:52] info: z2m:mqtt: MQTT publish: topic 'zigbee2mqtt/bridge/response/device/ota_update/update', payload '{"data":{},"error":"OTA update of 'Basement - Dehumidifier - Outlet' failed (OTA update of 0x4ce175b4dc440000 failed with reason: INVALID_IMAGE)","status":"error"}'

Progress climbed steadily and normally right up to the end (0% → 1.91% → 3.88% → ... → 98.91%) before failing — this doesn't look like a stalled or dropped transfer, it completes and is then rejected.

What did you expect to happen?

The device installs firmware 56 successfully.

How to reproduce it

  1. Have a ThirdReality Smart Plug Gen3 (USA variant, hw v1) on firmware 47.
  2. Trigger the OTA update to 56 (via HA's update.install service or the Z2M frontend).
  3. Watch progress climb to ~99%.
  4. Update fails with INVALID_IMAGE.

OTA file inspection

I downloaded bl702_plug_gen3_usa_1.00.56.ota directly (same URL Z2M fetches: https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/images/ThirdReality/bl702_plug_gen3_usa_1.00.56.ota, introduced in #1257) and parsed the ZCL OTA container header to rule out a corrupted/truncated download:

Field Value Notes
Magic number 0x0BEEF11E correct
Header version 0x0100
Header length 60 matches computed offset after optional fields
Field control 0x0004 Hardware Versions Present
Manufacturer code 0x1407 (5127) ThirdReality
Image type 0xD3BD (54205)
File version 0x00000038 (56) matches expected latest version
Min/max hardware version 0 / 65520 unrestricted, covers hw v1
Header string thirdreality
Declared total image size 282386
Actual file size on disk 282386 matches exactly
Sub-element tag 0x0000 (Upgrade Image), length 282320 60 + 6 + 282320 = 282386 — accounts for every byte, no truncation/trailing data

The outer ZCL OTA container is well-formed and not corrupted or truncated at the wrapper level. I don't have visibility into the BL702-vendor-specific firmware payload inside the Upgrade Image sub-element, so I can't rule out an issue with that inner blob's own integrity check (which is presumably what the device's bootloader is rejecting).

Given the container parses cleanly and the failure is 100% reproducible (not intermittent), a defect in this specific v1.00.56 payload seems more likely to me than transfer-layer corruption over the mesh — but I can't confirm that without BL702's image format spec.

Environment

  • Zigbee2MQTT version: 2.13.0-1
  • Coordinator: Home Assistant Yellow (EmberZNet/EFR32 radio)
  • Device: ThirdReality Smart Plug Gen3, hardware version 1
  • IEEE address: 0x4ce175b4dc440000
  • OTA file: images/ThirdReality/bl702_plug_gen3_usa_1.00.56.ota (added in update thirdreality plug gen3 to v1.00.56 #1257)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions