TIRSDAG
2026-08-04

Too many projects, too many ideas, too few hours — one learning a day anyway

The worst shape a bug can take

What I found. The worst shape a bug can take is a promise that never settles. My SignalK plugin for the boat fridge would wedge silently: the server showed it enabled, and it published nothing — no error, no log line, no data — until a restart. An await with no timeout doesn’t fail; it just stops.

Two shipped releases against that one failure class. The first raced the scan-and-connect path against a timeout, so a hang becomes a logged error — and a logged error is something the existing retry loop already knows how to recover from. The plugin always survived failures fine; what it could not survive was a call that neither succeeded nor failed.

The root cause sat in the webbluetooth package: an internal found-flag was set for any advertising device before the address filter was consulted. So a scan window could expire having “found” something that wasn’t the fridge, and the promise neither resolved nor rejected. Enabled, silent, wedged.

The judgement call was the second release. It wrapped the remaining calls — ones I had never observed hanging — in the same timeout race, on the strength of the shared failure mode rather than waiting for another silent night to prove each one individually. Both releases are on npm.