Skip to content

Stop crying wolf on transient network failures (1.7.18)#45

Merged
sturimcode merged 1 commit into
mainfrom
quiet-transient-failures
Jul 8, 2026
Merged

Stop crying wolf on transient network failures (1.7.18)#45
sturimcode merged 1 commit into
mainfrom
quiet-transient-failures

Conversation

@sturimcode

Copy link
Copy Markdown
Owner

Why

The 4-hourly Launch Agent fails most often because the network was briefly unavailable (the Mac asleep, Wi-Fi flapping) when the timer fired. These runs self-heal on the next attempt, but each one fired a "eufy-sync failed" notification. Over this machine's log lifetime that is 15 false alarms, which trains the user to ignore the notifications that actually matter (a bad password, a revoked token).

What

Headless runs whose failures are all transient network errors now stay silent until three land in a row, then fire one notification saying the network has been down a while and syncs are waiting. Any successful run resets the streak.

  • Real failures always notify immediately - bad password, revoked token, Garmin rate limit, profile ambiguity. Verified by an adversarial review that traced every real-failure message this codebase produces through the classification: none is silenced, precedence is correct, and a mixed failure set still notifies.
  • Interactive runs are never silenced - you are watching the terminal, so the error surfaces right away as before.
  • Persistent TLS problems are not treated as blips. A handshake that timed out is transient, but certificate verify failed / wrong version number (a wrong system clock, a stale CA bundle, or a TLS-intercepting proxy) are real and notify.
  • Classification lives in a new failure_notify module, tuned to httpx / requests / stdlib network shapes. The streak counter is a small state file under ~/.garmin-sync; corrupt contents reset it rather than crash the run.

Design decision

Escalate-after-3 (silent for isolated blips, one heads-up if the network is genuinely down ~12h) was chosen over always-soft-notify and fully-silent.

Testing

264 tests pass, run hermetically. New tests pin the classification (including the SSL-cert cases that must not be silenced and the httpx shapes that must be), the escalate-once-at-threshold logic, streak reset on success, corrupt-file robustness, and the headless-vs-interactive behavior end to end through main(). Reviewed adversarially for the one dangerous failure mode (a real failure being silently suppressed); confirmed clean.

🤖 Generated with Claude Code

A scheduled sync fails most often because the network was briefly gone (the
Mac asleep, Wi-Fi flapping) when the 4-hourly timer fired. Those runs
self-heal on the next attempt, but each one fired a "eufy-sync failed"
notification, which trains the user to ignore the notifications that matter.

Headless runs whose only failures are transient network errors (DNS, TLS
handshake timeouts, connection resets, "all connection attempts failed") now
stay silent until three land in a row, then fire one notification that the
network has been down a while and syncs are waiting. Any success resets the
streak. Real failures (bad password, revoked token, rate limit, profile
ambiguity) still notify immediately, every time, and interactive runs are
never silenced.

Classification is by message substring in a new failure_notify module, tuned
to catch httpx/requests/stdlib network shapes while leaving persistent TLS
problems (certificate verify failed, wrong version number - a bad clock,
stale CA bundle, or intercepting proxy) as real failures that notify. The
streak counter is a small state file; corrupt contents reset it rather than
crash the run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sturimcode
sturimcode merged commit 5d2264f into main Jul 8, 2026
4 checks passed
@sturimcode
sturimcode deleted the quiet-transient-failures branch July 8, 2026 23:35
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.

1 participant