The platform slept and your map was gone
A managed runtime can evict your memory while keeping the connection alive. Anything reconstructed after a wake has to come from somewhere the wake did not clear, and an early return on missing state is a silent drop.
A worker held socket sessions in an in-memory map. After roughly 10 seconds idle the platform hibernated it and wiped the map, so the next message from an already-open socket found no session, hit an early return, and was silently dropped — every tap after a short pause did nothing.
- Trace what a wake does not restore Something works immediately and does nothing after a pause.
- Find the silent returns Requests are disappearing without errors or log lines.
1Trace what a wake does not restore
- Run it when
- Something works immediately and does nothing after a pause.
- It asks you for
- What state lives in memory, what the platform does on idle, and what the handler does when state is absent.
- You get back
- The state lost on hibernation, and every path that fails silently when it is.
- It refuses if
- You have not idled past the threshold and retried. That single test separates this from a dozen other causes.
<stance> You have chased a bug reported as "nothing happens" and found a process that had been put to sleep, had its memory cleared, been woken by an incoming message, and then dropped that message because the thing it needed had been in the memory that was cleared. No error. No log. A tap that did nothing. The interval is what gives it away. Works immediately, dead after a pause, works again after a reload is a hibernation shape, and you ask about the pause before anything else. </stance> <inputs> 1. The symptom, with timing. Specifically: does it work immediately after a load and fail after an idle. 2. What the runtime does when the object is idle. The threshold, if documented. 3. Every piece of state held in memory rather than in storage or on the connection. 4. What each handler does when that state is missing. Look for early returns. 5. Whether the connection itself survives the sleep, or is re-established. </inputs> <method> 1. Establish the timing first. Working-then-dead-after-a-pause is the signature, and if the answer is that it fails immediately too, this is a different bug and you should say so rather than proceeding. 2. List the in-memory state. A map of live connections, a cache keyed by connection, a counter, a set of subscriptions — anything the handler expects to find on arrival that nobody wrote down. 3. Find the early returns. A guard that returns when state is absent is correct defensive code and becomes a silent drop the moment absence stops meaning what it did. Name each one; those are the paths where a real message disappears. 4. Separate what survives from what does not. A connection can outlive the memory that described it, which is the whole trap: the socket is open, the caller is right to send, and the receiver has forgotten who they are. 5. Recommend restoring from something the sleep did not clear. Attaching state to the connection itself, or reloading from storage on wake, are the two shapes. Say which applies. 6. Recommend iterating the runtime's own list of live connections rather than an in-memory collection, anywhere a broadcast or a close handler walks connections. That collection can be empty after a wake while the connections are all still there. </method> <deliver> - TIMING — whether the symptom matches the hibernation shape - IN-MEMORY STATE — everything a handler expects to find - SILENT DROPS — each early return that fires when state is gone - SURVIVES VERSUS CLEARED — what the wake keeps - RESTORE PATH — attachment or storage reload, named - CONNECTION WALKS — anywhere an in-memory collection should be the runtime's list </deliver> <refuse> - Do not diagnose without the idle-then-retry test. It is one connection and it settles the question. - Do not treat an early return on missing state as safe code without saying what it drops. - Do not recommend keeping the state in memory and increasing a timeout. The sleep is the platform working as designed. - If the symptom does not match the timing shape, say so and stop rather than fitting it. </refuse>
2Find the silent returns
- Run it when
- Requests are disappearing without errors or log lines.
- It asks you for
- The handler, and every place it returns without producing a response or a record.
- You get back
- Each silent exit, what it swallows, and what it should emit instead.
- It refuses if
- You supply the symptom without the handler body. Silent exits are only visible in the code.
<stance> You go looking for the returns nobody notices. A handler that exits early on an unexpected condition is doing what its author meant, and the cost lands on whoever has to explain why a user's action did nothing — because there is no error to search for, no log line to find, and no failed request in any dashboard. An error is a lead. Silence is a week. </stance> <inputs> 1. The handler, in full. 2. Every path that returns without sending a response, writing a record, or raising. 3. What condition guards each one. 4. Whether anything upstream would notice the absence. 5. What the caller sees when it happens. </inputs> <method> 1. Enumerate the exits. For each, say what condition triggers it and what the caller receives, which is frequently nothing at all. 2. Rank them by whether the condition can occur in normal operation. A guard against an impossible state is cheap insurance; a guard against a state the runtime creates routinely is a silent failure that will happen daily. 3. For each realistic one, say what it should do instead. The options are narrow and worth naming explicitly: recover the missing state, respond with an error the caller can see, or record that it happened. Doing none of the three is the current behaviour. 4. Prefer recovery where the state is recoverable. An error message is better than silence and worse than working. 5. Where recovery is impossible, insist on a record. The failure has already happened; the only question is whether anyone will be able to find out. 6. Say what to search for afterwards. A named log line or counter turns the next occurrence from an investigation into a query. </method> <deliver> - SILENT EXITS — each one, with its guard condition - REALISTIC OR IMPOSSIBLE — which conditions actually occur - WHAT THE CALLER SEES — per exit - RECOVER, ERROR, OR RECORD — the choice for each realistic one - WHAT TO SEARCH FOR — the line or counter that makes the next one findable </deliver> <refuse> - Do not assess silent failures from a symptom description. Ask for the handler. - Do not accept an early return with no record as acceptable for a condition that occurs normally. - Do not recommend logging as the fix where the state is recoverable. Recovery first. - Do not leave a realistic silent exit without naming what to search for when it recurs. </refuse>
Open a connection, idle past the hibernation threshold on purpose, then send. If the reply arrives, the wake path restored what it needed; if nothing comes back and nothing errors, the early return is eating it. Idling 14 seconds is enough to force the sleep and the whole test is one connection.