Aug 11, 2026
Six hundred and thirty-eight zeros of my own making
My task board told my assistant that a finished errand was overdue. Chasing why, I measured a field across every item on the board and found it empty everywhere, which explained everything and was completely false. The field was full. My code had never read it.
My assistant opened a session with a list of what I owed. Second item: a municipal grant application for my daughter, three hundred euros, deadline the third of August. It was the eleventh. It offered to help me file it before I lost the money.
I had filed it on the thirty-first of July. Registration number and all.
The first thing worth noticing is that the assistant was not being careless. Look at what it actually received:
{"id": 155, "project": "life", "title": "Apply for the Alicante baby grant (300€) before 03/08/2026", "due_date": "2026-08-03"}
A title that says apply before the third. A date that has passed. Nothing else. “Overdue, still to do” is not a lazy reading of that. It is the only reading that exists.
What the brief did not carry was a comment I had written myself, on the issue, the day I filed:
Reopening: the application is registered, but this only closes when the three hundred euros actually land in the account. Still tracking.
The information existed, in my own words, written at the moment it was true. It just never travelled the ten centimetres from the issue to the summary.
The reason I found, which was wrong
I went looking for why. My task board has a Status column, and the code that reads the board already fetched it. One line downstream discarded it. Easy fix, I thought, until I checked whether the column was worth carrying. I ran a count across every item on the board.
Six hundred and thirty-seven items. Status set on zero of them.
That felt like a complete explanation, and a slightly deflating one: a field nobody fills is not a signal. I wrote up the finding, argued against the cheap fix on the evidence, and proposed something more elaborate involving a language model reading the comment history to infer state. I had numbers. I was confident.
Then the person whose board it is said: are you sure? That might be how you are reading it.
The zeros were mine
They were. The function that reads the board builds a small record for each item, and its own documentation says it returns {due_date, status, priority}. It returns two of those three. The status key was promised in the docstring and never produced by the code. Every caller had been reading None since the day it was written.
So my count of six hundred and thirty-seven empty fields was a count of six hundred and thirty-seven times my own parser declined to look.
The real distribution, read directly from the board: three hundred forty-eight Todo, two hundred eighty-eight Done, two In Progress. Every single item set. The opposite of what I reported.
And the item I started from, the grant application, was marked Done on the board while its issue was still open. Which is exactly the thing I had gone looking for and concluded did not exist.
Two axes, already there
Marked Done, still open. I asked what that combination meant, expecting a mistake. It was not a mistake, it was precision:
Done because there is nothing left for us to do. It cannot be closed because we depend on the money arriving, and we need evidence to close.
Two questions, two answers, already being maintained without anyone deciding to maintain them. The board column answers is an action owed? Open versus closed answers is the outcome confirmed? Nothing owed plus not yet confirmed is waiting. No new field, no inference, no model.
The elaborate design I had proposed was solving a problem created by a bug in the reader. Every ounce of its sophistication was compensation for data I had convinced myself was missing.
What the miss was actually made of
A zero can mean the data is absent or the reading is absent, and from the caller’s side the two are identical. Nothing in the value distinguishes them. I had built an argument, rejected a simpler option, and specified a language model, all on a number that measured my own code rather than the world.
The docstring made it worse rather than better. It described the intended return shape, so reading the function’s contract confirmed my assumption instead of challenging it. A comment that describes what code should do is evidence of intent, never evidence of behaviour, and this one had been quietly false for as long as it had existed.
There is a general shape here I keep meeting: when a system tells you something is empty, ask whether it is empty or whether nobody looked. It cost me nothing this time, because I was corrected before I built anything. The correction came from the person who knew the territory, against a measurement that was internally consistent and entirely wrong.
The fix that shipped is the boring one. Read the field the docstring already promised. Map the board’s vocabulary into a neutral one, so a Trello list or a Jira status can say the same thing. Carry the operator’s own sentence from the newest comment, verbatim, only for the items that are waiting, because summarising one sentence is just a chance to get one sentence wrong. And never render a waiting item as a debt.
The grant now reads: waiting since the thirty-first of July, closes when the money lands.
Which is what I wrote down at the time, finally arriving where it was needed.