Skip to content

Collect repeated send failures in the stashed-errors view instead of flooding the log#2936

Merged
asgothian merged 1 commit into
ioBroker:masterfrom
krobipd:fix/dedupe-send-failure-log
Jul 12, 2026
Merged

Collect repeated send failures in the stashed-errors view instead of flooding the log#2936
asgothian merged 1 commit into
ioBroker:masterfrom
krobipd:fix/dedupe-send-failure-log

Conversation

@krobipd

@krobipd krobipd commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

The problem

A device that stops responding (left the network, powered off) turns every send into an error line: the ember driver rejects with Delivery failed for '<nwk>' and no error code, so filterError takes the no-code branch and logs every attempt at error level. With an automation still commanding the device (a scene, a bridge, a script), the send queue drains one failed attempt per ~5 seconds — that is one identical log line per ~5 seconds, around the clock:

Send command to 0xa4c13878b2fbd388 failed with no error code (Delivery failed for '26566'.)
Send command to 0xa4c13878b2fbd388 failed with no error code (Delivery failed for '26566'.)
...

Observed live: ~18,000 identical lines per day for a single dead bulb. Every other message drowns in between, and the flood does not even show when the problem started.

The fix — reuse the existing stashed-errors collection

The adapter already has exactly the right tool: the stashed-errors collection in the states controller (today used for the min/max value warnings and unknown models) — first occurrence is logged, repeats only bump a counter with first/last-seen timestamps, and the errors view in the admin tab plus info.lasterror show the live state.

This PR routes the error-level branches of filterError (no error code, unknown code, E_ERROR, malformed) through that collection when the caller provides a stash key; without a key the behaviour is byte-for-byte unchanged. The send path in publishFromState passes send:<device> as key and clears it again on the first successful send to that device — so a later outage starts with a fresh error line instead of counting silently. Clearing recalculates hasData, so the errors button disappears once everything is resolved. The first logged line carries a short hint that repeats are counted, not logged.

The info/warn/debug severities of the error-code table (9999 → info, 233 MAC NO ACK → debug, 205/134 → warn) are deliberately untouched — those are already rate-appropriate.

Resulting behaviour for a dead device

  • outage starts → one error line (as today, plus the hint)
  • while it lasts → no further log lines; the errors view shows message | count | first seen | last seen live, info.lasterror is updated per occurrence
  • device recovers, first send succeeds → collection entry cleared
  • a new outage later → again exactly one fresh error line

Verification

  • 23-case functional test against the real modules (main.js filterError/logFilteredError + the real StatesController): one line then silence, counter/timestamps/info.lasterror, reset-on-success, fresh logging after reset, hasData recalculation with and without remaining entries, no-key behaviour unchanged (two calls = two lines), coded paths info/warn/debug unchanged and not collected, unknown-code path collected, existing min/max stash behaviour unchanged
  • node --check on all touched files, ESLint clean, npm test green

Note: the filterError call site in publishFromState overlaps with a line #2934 touches (the devLabel model parameter). Whichever lands second, I will rebase immediately.

🤖 Generated with Claude Code

A device that stops responding (left the network, powered off) turns
every send into an error line: the ember driver rejects with 'Delivery
failed' and no error code, so filterError logs each attempt at error
level. With an automation still commanding the device this fills the
log with one identical line per ~5 seconds - tens of thousands of lines
per day for a single dead bulb, drowning every other message, while not
even showing when the problem started.

The adapter already has the right tool for exactly this situation: the
stashed-errors collection in the states controller (used for the
min/max value warnings and unknown models) - first occurrence is
logged, repeats only bump a counter with first/last-seen timestamps,
visible in the errors view of the admin tab and in info.lasterror.

This change routes the error-level branches of filterError (no error
code, unknown code, E_ERROR, malformed) through that collection when
the caller provides a stash key; without a key the behaviour is
unchanged. The send path in publishFromState passes 'send:<device>' as
key, and clears it again on the first successful send to that device
(new unstashError, which also recalculates hasData so the errors
button disappears once everything is resolved) - a later outage starts
with a fresh error line again. The first logged line carries a short
hint that repeats are counted, not logged.

The info/warn/debug severities of the error code table are deliberately
untouched - those are already rate-appropriate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@asgothian asgothian merged commit 60eede8 into ioBroker:master Jul 12, 2026
7 of 36 checks passed
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.

2 participants