The second instalment of this log ended with a dated paragraph about three builds that went out on 9 September, and it filed them under the same heading as the rest: things that existed but were not yet behaving like objects. That was true and it was not the story. The story is what those three builds and the two after them add up to, and it finished on the tenth.
The short version: the game's own way of telling us it had broken was itself broken, in a way no log could show. Everything shipped since is one answer to that.
Four Doors, All Silent
The Lot has a bug reporter. Press F11, or use the button in the pause menu, or either of two buttons on the main menu, and a form opens that captures where you were standing, what the world was doing and a screenshot, and sends it to us. For some people, on some machines, none of those four doors did anything. No form, no error, no line in any log. The buttons simply did not work, and the app gave no sign of why.
Every one of those entry points was written as Instance?.OpenForm(...). That is the null-conditional: if the reporter object exists, open the form; if it does not, do nothing. It compiles, it runs, and with a missing reporter it does exactly what it says, which is nothing, silently, on every version, for ever. A null there was never a degraded reporter. It was four dead buttons with no trace anywhere.
The reporter could be missing because it was built seventh inside one boot method that constructed eighteen components in a row, with nothing between the steps. In that arrangement any component earlier in the line that failed while starting deleted the reporter and everything after it. The pause menu is built elsewhere, which is why a player in that state still had a pause menu with a button on it that did nothing.
We learned about it because a report reached us by a route other than the app, which is the only way it could have. A build meant to harden the report itself had gone out in between and had not touched the door, because the door was not where anybody was looking.
The rule that came out of it
The thing that reports failures must not depend on anything it reports on. Three changes follow from that sentence and all three shipped in 0.54.2. The reporter's Instance heals itself: if it is missing, it adopts a stray one or builds a new one, because the reporter is what you reach for when the rest of the game is broken. There is one door, Open(crash, from), that every caller uses, and it either opens the form or says why not, in the log, every time. And the boot chain fences each step so one bad start cannot cascade, with the reporter built first, because it is the thing that reports the others.
The Same Shape Everywhere Else
A bug with a shape is worth more than a bug, because you can search for the shape. So the next build was a sweep for it.
The builder that starts a world had the same unguarded chain: twelve steps in one sequential method, guarded only by null checks for idempotence, which is not protection. The three most exposed entries enumerate your displays, enumerate your windows and launch a process, the most machine-dependent things this project does, and below them sat the pause menu and, deliberately last of all, the main menu. So a display quirk on somebody else's computer could take away the front door and leave them staring at a world they could not log into, with nothing in the log. Each step is fenced now, and a step that has trouble says so instead of quietly removing everything after it.
Then the controls. Twenty-three of them, every one reached from a click, every one written Instance?.Whatever(). The launcher and the palette gained a Required() helper that keeps the null-conditional, because an input handler still must not throw, but logs, naming the calling method, when the thing it needed was not there. Two were worse than dead: the pause menu's hotkeys button closed the menu before asking for the panel, so with a missing panel it dismissed the menu and opened nothing, and looked like it had worked. Both now check first, say so, and leave the menu standing.
What this is not
It is not a guarantee that a bad start can no longer hide anything. The sweep was triaged rather than rewritten wholesale: most of what the search found was correct as written, and saying which was the point of doing it by hand. What changed is that the places where silence was possible are now places where a failure is named, which is a smaller claim and a true one.
Three Routes In, Each Sending Less Than the Last
Once the door worked, the question was what should be able to come through it, and the answer became three routes with three different amounts of information, because they are chosen in three different situations.
The in-game form. F11 or the pause menu. This is the full one: your position, the world state, performance data and a screenshot, because you are filling it in, you can see what it contains, and you pressed the button.
The website form, for when the app will not open at all. It sends only what you type, plus your browser and screen size, and a screenshot only if you attach one yourself. No position, no world state, no performance data, no log, and the page says so in as many words, because a browser cannot see where you were standing and does not ask the app.
Automatic error reports, which are the new thing. First-run setup asks once, with the box unticked, and the answer lives in the pause menu after that. Switched on, and only when a session actually logged an error, The Lot queues one report as it closes and sends it the next time you open the app. It carries the application's own error log, the build number, your GPU, Windows version and resolution, the name of the environment you were in, what the app was doing when it closed, and a block of counts: how many displays, how many panes, how much memory. Nothing else.
Why the automatic one sends no picture
Nobody chooses what is on screen at the moment they close a program. A screenshot you attach to a form is one you looked at first; a screenshot taken at quit is not, so this route never takes one. It also never sends your position, anything you typed, or Windows' own Player.log, which can carry window titles and the addresses of pages you opened. The app keeps its own, narrower error log precisely so that there is something safe to send, and that distinction had to survive this feature or the feature could not exist.
Two more details from the same commit, because they are the kind that matter and never make a feature list. The report is queued at shutdown and sent on the next launch, not uploaded during quit: an upload started inside the closing of a process races the exit and generally loses, and the report you must not gamble on is the one nobody is watching. And a session that logged no failures queues nothing at all, because an empty report every session trains whoever reads the inbox to ignore the inbox.
The Opt-In That Would Have Reached Nobody
The pre-ship audit of that feature found two things that were bugs rather than tidying, and both are worth writing down because they are the same shape as everything above: a thing that appears to work and reaches no one.
"Pending" meant "first launch". Every existing player had finished onboarding months ago, so the one place the question was asked had already been passed by everyone the feature was built for, and the switch would have stayed off for ever with nobody ever seeing the choice. It is per-question now: outstanding if your name is unset or the report question has never been asked, and an existing player sees only the question they have not answered. The second finding was that the hidden name field still carried a suggested value and the Done button still read it, so answering the report question would have silently renamed an existing player to their Windows username. Both fixed before it shipped, and the fix was verified by driving the exact path rather than by reading it.
The server had a smaller version of the same thing waiting. The endpoint that receives reports normalises an unknown category to other, and the new automatic category was unknown to it, so automatic reports would have arrived indistinguishable from ordinary feedback. auto is a valid category now, and the notification subject carries which kind arrived.
L Shows You What Would Leave
The honest way to ask somebody to trust an automatic report is to let them look at what one contains. Press L and the error log is on screen: the same entries an automatic report would send, in the same order, and nothing else, with a footer that says which way your own switch is currently set. It is rebindable like every other key. And Copy all puts the whole thing on the clipboard, which exists for exactly the case that started this: a report window that will not open can still be pasted into a message.
Two things caught while building it, both ours. The window inherited a translucent style from the report form, which gets away with it because it opens over a dark interior; this one opens wherever you are standing, and over sunlit grass the stack traces vanished into the lawn. Solid backing now. And the Wrap toggle did nothing: the draw loop computed a style from it and then drew with the wrapping one regardless, a checkbox that ticks and changes nothing, which is the dead-control shape this whole log is about, found in the tool built to catch it.
It Paid for Itself Within Two Days
0.55.1 fixed the radio screen. It had three reported symptoms: no title bar, it never resized or came to you when focused, and the wall sign kept saying the tuner was closed while the window was open. They were one fault. A resize was being applied to the web view a frame or two before the view had finished initialising, the resize threw, and the throw landed mid-method and took the rest of the method with it: the title bar is set after the resize, the bring-to-you is started after it, the sign is updated after it.
What found it was not the reading of slot state, which went on for several rounds. It was the toast in a screenshot, the one that says something broke and that F11 sends us a report, sitting there while an exception with a full stack trace sat in the log. The reporter built two days earlier was pointing at the answer the whole time.
The generalisable half
When several symptoms appear at once in one place, look for the one throw that stopped a method partway through, before you look for three bugs. And when the tool you built to say something broke says something broke, read what it wrote before you start guessing. The second rule is embarrassing to need. It was needed.
Where It Actually Is
The Lot is a private playtest, invite-only, and the served build this morning is 0.55.1, in both the installer and the archive shape, confirmed on the server rather than read off the page. The privacy policy moved with all of the above: its first sentence about what we receive now says that a report is something you chose to send, by filling one in or by switching the automatic ones on, and that nothing runs by default. That sentence was true before this fortnight and it is more true now, because there is finally a way to check it from inside the app.
If you want the other two instalments, instalment one is about what we refused to ship, and instalment two is the five builds that were mostly the same bug. The same discipline shows up elsewhere this week: the two names every Shopify app has is a link that was named right and still went nowhere, which is a dead button of a different kind, and knowing it broke before your users do is the server-side version of building the reporter first.