{"record":{"id":"b48c07888fac5f44","repo":"pydantic/monty","slug":"task-has-no-frames-and-no-coroutine-id","errorCode":null,"errorMessage":"task has no frames and no coroutine_id","messagePattern":"task has no frames and no coroutine_id","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/monty/src/bytecode/vm/async_exec.rs","lineNumber":699,"sourceCode":"            // frames have already been saved, so route already-awaited failures\n            // through `handle_task_failure`, which restores the waiter before\n            // the error propagates.\n            let HeapReadOutput::Coroutine(coro) = self.heap.read(coro_id) else {\n                panic!(\"task coroutine_id doesn't point to a Coroutine\")\n            };\n            let is_new = coro.get(self.heap).state == CoroutineState::New;\n            // Release the handle before either branch: both go on to drop\n            // references to this coroutine, and freeing it under a live\n            // reader panics.\n            drop(coro);\n            if is_new {\n                self.init_task_from_coroutine(coro_id)?;\n            } else {\n                return self.handle_task_failure(ExcType::cannot_reuse_already_awaited_coroutine());\n            }\n        } else {\n            // This shouldn't happen - task with no frames and no coroutine\n            panic!(\"task has no frames and no coroutine_id\");\n        }\n\n        // Resolutions that landed while this task was parked already pushed\n        // their value onto `task.stack` (via `deliver_value_to_task` or\n        // `handle_task_completion`'s waiter-handoff branch), so the restored\n        // stack above is already in the post-AWAIT shape.\n\n        Ok(())\n    }\n\n    /// Initializes the VM state to run a coroutine for a spawned task.\n    ///\n    /// Similar to exec_get_awaitable's coroutine handling, but for task initialization.\n    fn init_task_from_coroutine(&mut self, coroutine_id: HeapId) -> Result<(), RunError> {\n        let HeapReadOutput::Coroutine(mut coro) = self.heap.read(coroutine_id) else {\n            panic!(\"task coroutine_id doesn't point to a Coroutine\")\n        };\n","sourceCodeStart":681,"sourceCodeEnd":717,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty/src/bytecode/vm/async_exec.rs#L681-L717","documentation":"load_or_init_task requires every scheduler task to carry either saved frames or a coroutine_id; a task with neither cannot be resumed. Hitting this panic means a task record was created or mutated into an impossible empty state. It is an interpreter-internal invariant, not reachable from sandboxed Python code.","triggerScenarios":"A task in the scheduler has neither stack frames nor a coroutine_id when the scheduler tries to load it — e.g. task state was partially torn down but the task was left in the ready queue, or a Task was constructed without either field populated.","commonSituations":"Seen when modifying task teardown/completion paths in async_exec.rs so a Completed task remains schedulable, or when adding a new task-creation site that forgets to set coroutine_id.","solutions":["Ensure task completion removes the task from all scheduler queues before clearing frames/coroutine_id","Check every Task constructor/spawn call site sets exactly one of frames or coroutine_id","Add an assertion at task creation validating the frames-xor-coroutine_id invariant","Report the reproduction upstream if hit without local modifications"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the invariant: every schedulable task has frames or a coroutine_id","Remove tasks from queues atomically with state teardown","Add a creation-time assertion for the frames-xor-coroutine_id invariant"],"tags":["async","internal-panic","scheduler"],"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-14T16:17:12.679Z"}