The upload that could never succeed
For four days the buoy asked, every fifteen minutes, to deliver one wave recording. For four days the server said no. Both of them were behaving exactly as designed. Which is how the best bugs always introduce themselves.
A conversation going nowhere
Occasionally we ask the buoy for the whole recording: not the four summary numbers she normally reports, but all six thousand raw motion samples behind them, so we can re-run her maths on shore and check her working. Because raw data is heavy and her SIM plan is not infinite, these are granted like library loans: a counter, counted down only when a delivery is confirmed received.
That confirmation rule is the safety net. A failed delivery costs nothing and is simply retried next time. And that same rule turned a small mistake into a very patient loop. Four days earlier, a firmware update had taught her to include three extra channels in the recording (the gyroscope, so the fusion can be re-run offline). The server-side update that should have taught the receiving end about six channels only taught the CSV export. The doorman never got the memo. Every recording she offered was rejected at the door as malformed; every rejection told her the delivery hadn't happened; so she kept the loan and tried again next wake. Forty-six hundred samples, beautifully compressed, offered over LTE roughly 380 times.
The fix that needed no reflash
The repair was two lines on the server: accept six channels where it previously insisted on three. Nothing had to be sent to the buoy at all. On her very next check-in, the same recording she had been faithfully re-offering for four days finally walked through the door. Delivered, decoded, verified sample-for-sample. There is something quietly wonderful about a fix where the patient heals herself the moment the world stops being wrong about her.
But the deeper bug was on the buoy, and it got its own fix in the next firmware: a rejection is not a failure. A network drop means try again later; a server that has examined your recording and declared it unacceptable means this will never work. Burn the loan, write down why, move on. Machines should be persistent about the retryable and honest about the unretryable.
What four days of asking costs
Each doomed offer was ~12 KB over cellular, plus the radio time to send it. Roughly a megabyte a day of SIM budget and a steady tax on the battery, on top of a charging policy that was already being too careful. Which brings us to the second fix of the day.
Stop wasting the afternoon
To keep the lithium cell alive for years inside a hot sealed hull, the firmware deliberately stops charging at a modest voltage instead of cramming the battery full. Good policy, wrong arithmetic: on a sunny day she was done by late morning, threw away the entire afternoon of solar, and went into every night around 70%. Three cloudy days in a row recently walked her down to the emergency floor, and a human had to intervene.
The new firmware keeps the gentle policy for most of the day but adds a dusk top-up: in the late afternoon, when the hull is past its heat peak, the ceiling rises and she charges properly full, then immediately starts spending it, so the cell is never held at high voltage, which is the thing that actually ages it. She now enters the night with a full tank instead of two-thirds of one. The battery chemistry gets its longevity; the winter nights get their reserve.
Writing it all down
The uncomfortable part of the stuck-upload story is not the bug. It's that the loop ran for four days without anyone noticing. The grant was issued, and then… nothing, invisibly. So the ops dashboard grew a ledger: every command an operator sends, every judgment the server makes on its own, and (crucially) every acknowledgement from the buoy herself, in one auditable trail. A raw-data loan now reads like a story with three acts: granted by a named human · handed to the buoy in a downlink · delivered and confirmed. An act that never arrives is no longer silence. It's a visible gap with a timestamp.
Every actor in this story followed its rules perfectly. The buoy retried, the doorman refused, the counter waited. The system failed anyway, in the gap between two correct components. That gap is where instruments live or die, and the only tool that works there is making the invisible visible.