The ceiling nobody had reached
Accepting an offer in production returned “Internal Server Error”. The player had £21,002,907 and the offer was £1,080,200.
The cash column was a 32-bit integer. On Postgres that is int4, whose
ceiling in pence is £21,474,836.47. The commit could not store the
result.
It was not this offer, or this screen. Every action that would have taken a company past that figure failed exactly the same way. A hard ceiling on the entire game, found the first time anybody got near it.
What makes this worth writing down is why it went unseen. The test suite and both simulation tools run on SQLite, which stores every integer as 64-bit and never overflows. The day-by-day simulation reached £259m without a murmur. No amount of playing the game in the test environment would ever have caught it — the bug lived entirely in the difference between the database the tests use and the database production uses.
So the test that now guards it does not play the game at all. It checks the declared column types: every money column must be a 64-bit integer. That was verified by putting the old type back and watching it fail, naming the column.
All sixteen narrow money columns were widened, not just cash. The next one to go would have been an auction bid on a large lot.
The general lesson is uncomfortable, because the SQLite-for-tests decision is a good one and I would make it again. It just means a whole category of bug is invisible to every test you write, and the only defence is to test the schema rather than the behaviour.