on_time (onWithTimedOff) throws a raw RangeError instead of a clear validation error above 6553.5s
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 15.7k
- Forks
- 2k
- Avg merge
- 18h 55m
- Merged PRs (30d)
- 35
Description
What happened?
When on_time (or off_wait_time) is set to a value that, once converted to tenths of a second, exceeds the ZCL 16-bit limit, Zigbee2MQTT lets an unhandled RangeError [ERR_OUT_OF_RANGE] bubble up from Node's buffer layer instead of validating the input first.
Root cause: the converter simply multiplies seconds by 10 before sending, with no bound check:
{ctrlbits: 0, ontime: Math.round(onTime * 10), offwaittime: Math.round(offWaitTime * 10)}
Since the ZCL OnTime / OffWaitTime fields are uint16, the real ceiling is 6553.5 s (1h49min), not 65535 s as the on_time parameter might suggest.
| on_time sent | value sent to device | result |
|---|---|---|
| 60 | 600 | 1 min OK |
| 1000 | 10000 | 16 min 40 s OK |
| 3600 | 36000 | 1 h OK |
| 10800 | 108000 | RangeError, since it is > 65535 |
This is closely related to #25323, which reported the same crash but framed it as wanting the ceiling raised past ~1h49 (not achievable, it's a ZCL protocol limit, not a Z2M bug). The remaining, narrower issue is that Z2M doesn't validate the value before sending it and lets a raw Node error through, unlike similar converters (e.g. toggle_wait_cmd for TS011F_plug_1, which checks the range up front and throws a clear, catchable error).
What did you expect to happen?
A clear, catchable validation error (e.g. "on_time must be between 0 and 6553.5 seconds") instead of an unhandled RangeError originating from the ZCL/buffer layer.
How to reproduce it (minimal and precise)
zigbee2mqtt/<friendly_name>/set
{"state": "ON", "on_time": 10800}
Result:
RangeError [ERR_OUT_OF_RANGE]: ZCL command .../1 genOnOff.onWithTimedOff({"ctrlbits":0,"ontime":108000,"offwaittime":0}, ...) failed (The value of "value" is out of range. It must be >= 0 and <= 65535. Received 108000)
Suggested fix
Add a bound check (0-6553.5s) on on_time / off_wait_time in the shared converter, before calling entity.command('genOnOff', 'onWithTimedOff', ...), mirroring the existing validation pattern used in toggle_wait_cmd.
Zigbee2MQTT version
2.13.0
Adapter
SMLIGHT SLZB-06M
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read the shared converter that builds the genOnOff onWithTimedOff payload, then compare its range-checking pattern with toggle_wait_cmd. Reproduce the issue with an on_time of 10800 and add focused coverage so values through 6553.5 seconds succeed while larger on_time or off_wait_time values produce a clear, catchable validation error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- embedded-iot
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100