On 4 October I found a bug in how my app reads SEC filings. I fixed it the same day and deployed it. On 5 October I published the dataset to Zenodo, got a permanent DOI, and told people they could cite it.
The dataset still had the bug.
Not a new bug. The same one. Fixed, deployed, live in production — and still sitting in 533 rows of the file I had just attached a DOI to.
What the bug was
Institutional managers in the US file a quarterly form called 13F listing what they own. Until the end of 2023 they reported position values in thousands of dollars. The SEC changed the convention to whole dollars.
My parser handled this the obvious way: if the filing is dated after the cutover, read dollars.
Three filers never switched. Baupost, Duquesne and T. Rowe Price kept filing in thousands, years after everyone else moved. So a $5.4 billion position was stored as $5.4 million. One thousand times too small, in a dataset whose entire purpose is comparing position sizes.
How I found it, which was not by reading the spec
I did not find this by checking the rules. I found it with a derived check that has nothing to do with units: divide the reported value by the reported share count and you get an implied price per share. Compare that to the actual closing price that week.
For 310 of the 325 manager-quarters, the ratio was exactly 1.0. For 15, it was 1/1000. Nothing in between. A clean bimodal split is not a rounding problem — it is two unit systems in one table.
T. Rowe Price was showing 7 to 15 cents a share. That is the kind of thing you see instantly in a ratio and never in a total.
Two witnesses before touching anything
The rule I work to is that nothing rewrites stored data on a single piece of evidence. Two independent witnesses, or leave it alone and log a warning.
Witness one was the market: implied price at 1/1000 of the close, across at least three equity positions.
Witness two was the filer's own cover page. Every 13F carries a total — and that total is in the same unit as the table, so on its own it proves nothing. What it gives you is a scale you can compare against that same filer's last pre-2023 filing. Anyone who switched to dollars jumps by a factor of 257 to 33,000. Anyone who never switched stays within a factor of three of their old self.
The second witness is the one that gets skipped, because the cover total looks like proof. It is not. It is the sum of the same numbers in the same wrong unit.
There is also a trap in the obvious shortcut. 13F has a $100M reporting threshold, so you might think anything reading below it must be in thousands. T. Rowe read as $999M. Only the history catches that one.
And then the part I actually want to tell you about
I fixed the parser. I wrote tests. I deployed. Twelve manager-quarters would now ingest correctly, forever.
The 533 rows already in the database did not move.
Of course they didn't. The value is computed once, at ingest, and written down. Fixing the thing that computes it changes what the next ingest writes. It does not reach backwards. I knew this. I have a note to myself that says exactly this. I published anyway, because "the fix is deployed" felt like "the bug is gone", and those are different sentences.
It took a separate repair script, a dry run, a backup and a second verification pass before the stored rows were right — two days after the fix went live.
The DOI part
A DOI is permanent. That is the entire point of a DOI. You can publish a new version and the concept DOI will redirect to it, but the version people downloaded is the version they have.
So there is a v1 of my dataset in the world with 533 wrong values in it. v2 is up, the concept DOI points at it, and the change is documented in the README. That is the best available outcome and it is still worse than waiting one more day.
What I would tell you
Three things, in the order of what they cost me:
"Deployed" and "repaired" are different states. If your product derives a value and stores it, every fix needs a second question: what happens to the rows that are already there?
Build checks that do not depend on the thing being checked. A unit bug is invisible to a unit check and obvious to a price check.
Before you make something permanent — a DOI, a release, a public API shape — assume the fix you shipped yesterday has not finished landing.
I build Talval, which values public companies from their filings. The 13F dataset is free and CC BY if you want it.




