{"record":{"id":"c78a8a222c09529a","repo":"pydantic/monty","slug":"checked-above-worker","errorCode":null,"errorMessage":"checked above","messagePattern":"checked above","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/monty-proto/src/worker.rs","lineNumber":573,"sourceCode":"        let Some(call_id) = expected_call_id else {\n            return protocol_violation(\"ResumeCall without a suspended function/OS call\");\n        };\n        if resume.call_id != call_id {\n            return protocol_violation(&format!(\n                \"ResumeCall call_id {} does not match {call_id}\",\n                resume.call_id\n            ));\n        }\n        let Some(wire_result) = resume.result else {\n            return protocol_violation(\"ResumeCall has no result\");\n        };\n        // NotHandled resolves against the suspended call itself — the child\n        // owns the no-handler semantics (`OsFunctionCall::on_no_handler`), so\n        // the parent never has to compute or echo the default exception.\n        let result: ExtFunctionResult =\n            if matches!(wire_result.kind, Some(pb::ext_function_result::Kind::NotHandled(_))) {\n                let SessionState::Suspended(progress) = &self.state else {\n                    unreachable!(\"checked above\");\n                };\n                let ReplProgress::OsCall(call) = progress.as_ref() else {\n                    return protocol_violation(\"NotHandled is only valid answering a suspended OS call\");\n                };\n                ExtFunctionResult::Error(call.function_call.on_no_handler())\n            } else {\n                match wire_result.try_into() {\n                    Ok(result) => result,\n                    Err(err) => return protocol_violation(&format!(\"invalid result: {err}\")),\n                }\n            };\n        let SessionState::Suspended(progress) = mem::replace(&mut self.state, SessionState::Configured(None)) else {\n            unreachable!(\"checked above\");\n        };\n        let mut print = ProtoPrint::new(sink, self.print_flush_interval);\n        let outcome = match *progress {\n            ReplProgress::FunctionCall(call) => call.resume(result, PrintWriter::Callback(&mut print)),\n            ReplProgress::OsCall(call) => call.resume(result, PrintWriter::Callback(&mut print)),","sourceCodeStart":555,"sourceCodeEnd":591,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-proto/src/worker.rs#L555-L591","documentation":"In `handle_resume_call` (crates/monty-proto/src/worker.rs:573) the `NotHandled` branch asserts the session is `Suspended` with `unreachable!(\"checked above\")`. An earlier guard on `self.state` should have established `SessionState::Suspended`; if the state is not suspended when a `NotHandled` result arrives, the worker panics rather than returning a protocol violation.","triggerScenarios":"A `ResumeCall` request with `kind = NotHandled` arriving while `self.state` is not `SessionState::Suspended` — e.g. resuming a session that was never suspended, or whose suspension was already consumed by a previous resume.","commonSituations":"A buggy parent sending two resumes for one suspension; protocol refactors that moved or removed the earlier `Suspended` check; replaying a request against a session in the wrong phase.","solutions":["Ensure the parent sends at most one resume per suspension and only while the child reported a suspended progress event.","In worker.rs, collapse the check: perform the `Suspended` extraction once and return `protocol_violation(\"resume requires a suspended session\")` on mismatch instead of panicking.","Check git history around line 573 for a refactor that separated the guard from the unreachable and reunify them.","Replace the worker if this fires in production — the pool will detect the crashed child and respawn it."],"exampleFix":"// before\nlet SessionState::Suspended(progress) = &self.state else { unreachable!(\"checked above\") };\n// after\nlet SessionState::Suspended(progress) = &self.state else {\n    return protocol_violation(\"NotHandled requires a suspended session\");\n};","handlingStrategy":"validation","validationCode":"// Parent: answer each suspension at most once\nif (!suspended || alreadyResumed) throw new Error('no pending suspension to answer with NotHandled');","typeGuard":"const isSuspended = (s: SessionState): s is { kind: 'Suspended' } => s.kind === 'Suspended';","tryCatchPattern":"try { await session.resume({ notHandled: true }) } catch (e) { if (e instanceof MontyCrashedError) pool.replace(); }","preventionTips":["Track suspension state on the parent side; never resume twice.","Return protocol_violation from the child instead of unreachable! for wrong-state frames.","Add tests for NotHandled answered outside a suspended OS call."],"tags":["state-machine","internal-panic","worker"],"backgroundTag":"internal-invariant-violation","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}