Sentry: ANTHIAS-3E — 875 events in <1 day from a pi5 on 2026.7.0+87e8259.
asset_loop sleeps between image/web assets via skip_event.wait(timeout=duration) (src/anthias_viewer/__init__.py:1445) with duration = int(asset['duration']) taken straight from the DB row. A large enough duration (> ~292 years in seconds, i.e. anything past C PyTime_t nanosecond range) makes threading.Event.wait raise OverflowError: timestamp too large to convert to C PyTime_t.
The exception propagates asset_loop → start_loop → main — the viewer process dies, the container restarts, the scheduler picks the same asset, and the device crash-loops indefinitely. That's what 875 events from a single device means: the screen is down.
Nothing server-side prevents an absurd duration from reaching the viewer (API-set or hand-edited row).
Fix shape:
- Viewer: clamp/validate the duration on read before using it as a wait timeout (defensive, same spirit as
clamp_refresh_interval two branches up).
- Server: reject/clamp out-of-range durations in the API serializers so the row never goes bad in the first place.
Sentry: ANTHIAS-3E — 875 events in <1 day from a pi5 on
2026.7.0+87e8259.asset_loopsleeps between image/web assets viaskip_event.wait(timeout=duration)(src/anthias_viewer/__init__.py:1445) withduration = int(asset['duration'])taken straight from the DB row. A large enough duration (> ~292 years in seconds, i.e. anything past CPyTime_tnanosecond range) makesthreading.Event.waitraiseOverflowError: timestamp too large to convert to C PyTime_t.The exception propagates
asset_loop → start_loop → main— the viewer process dies, the container restarts, the scheduler picks the same asset, and the device crash-loops indefinitely. That's what 875 events from a single device means: the screen is down.Nothing server-side prevents an absurd duration from reaching the viewer (API-set or hand-edited row).
Fix shape:
clamp_refresh_intervaltwo branches up).