Entity Does Not Exist in the World
Written later and filed to this date, as part of filling in every day of the year.
On a phone there is no console. When a browser game freezes on a phone, the player has a black screen and nothing to say about it, and until a Saturday in July that was the entire bug-reporting pipeline for a survivor shooter I run on the open web: a frozen game, a shrug, a reload.
That Saturday’s commit changed it. The crash overlay gained a button, COPY ERROR LOGS, behind which sits a fifty-entry ring buffer wrapped around the console’s error and warning channels at startup. Tap it and the clipboard gets the fatal error with its stack, a timestamp, the user agent, the viewport, and the last fifty things the game had complained about before it died.
The first field report arrived the next evening. The fatal line read bitECS - entity does not exist in the world, thrown from a consumable pickup. The floor item that freezes every enemy iterates a per-frame cache of enemy ids, and that cache can hold an entity that was killed and recycled earlier in the same frame. Adding a component to a recycled id throws, and an uncaught throw inside the engine’s update loop halts the game on the overlay.
The fix is four early returns: every status applier, burn, freeze, poison and chain immunity, now checks that the entity still exists before touching it, so any caller holding a stale id is safe at the one choke point. One test pins the exact shape, an id removed mid-frame, and asserts the applier still works on the live ones.
But the report had carried fifty lines, and one of the warnings nobody had asked for said that a relic referenced an icon key thorn when the map’s key is thorns, and had been drawing the fallback glyph instead. That is a different class of bug: a string in one data table not matching a string in another, invisible to the type checker, visible only on the screen of someone who knew what the icon should be.
So the same evening grew a second commit: a sweep over every catalogue in the game, relics, cards, upgrades, weapons, achievements, milestones and ship mod tracks, asserting that every icon key resolves without fallback, with a floor of a hundred references so that an emptied sweep fails instead of passing vacuously. And the test suite moved into the deploy job, so a red test blocks the deploy rather than a player’s run.
The sweep’s first run in CI found twenty-one more dangling icon keys, eight relics, seven achievements, six milestones, every one of them rendering a cross-mark in production for however long it had been there, and none of them mentioned in the crash report.