{"record":{"id":"bc49942166d3986a","repo":"nautechsystems/nautilus_trader","slug":"task-slot-is-already-occupied","errorCode":null,"errorMessage":"task slot is already occupied","messagePattern":"task slot is already occupied","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/live/src/task.rs","lineNumber":648,"sourceCode":"    pub const fn is_none(&self) -> bool {\n        self.handle.is_none()\n    }\n\n    /// Returns the owned task handle, when present.\n    #[must_use]\n    pub const fn as_ref(&self) -> Option<&JoinHandle<T>> {\n        self.handle.as_ref()\n    }\n\n    /// Stores a task in an empty slot.\n    ///\n    /// # Panics\n    ///\n    /// Aborts `handle` and panics if the slot already owns a task.\n    pub fn insert(&mut self, handle: JoinHandle<T>) {\n        if self.handle.is_some() {\n            handle.abort();\n            panic!(\"task slot is already occupied\");\n        }\n        self.handle = Some(handle);\n        self.abort_requested = false;\n    }\n\n    /// Requests task cancellation and records it as owner-initiated.\n    pub fn abort(&mut self) {\n        if let Some(handle) = self.handle.as_ref() {\n            handle.abort();\n            self.abort_requested = true;\n        }\n    }\n\n    fn complete(&mut self, result: Result<T, JoinError>) -> TaskJoinOutcome<T> {\n        let outcome = match result {\n            Ok(output) => TaskJoinOutcome::Completed(output),\n            Err(e) if e.is_cancelled() && self.abort_requested => TaskJoinOutcome::Aborted,\n            Err(e) => TaskJoinOutcome::Failed(e),","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/task.rs#L630-L666","documentation":"This panic comes from `TaskSlot::insert` in the live execution engine's task runner. A task slot holds at most one `JoinHandle`; calling `insert` while the slot already owns a task aborts the NEW handle and panics, because two tasks sharing one slot would orphan a join handle and leak the running task. It is an internal lifecycle invariant of the live engine, not a condition user data can normally cause.","triggerScenarios":"Calling `slot.insert(handle)` twice without an intervening `take()`/completion of the slot's current task; e.g. a live data or exec client spawning its heartbeat/reconnect/task twice for the same slot (duplicate connect(), double initialization, or re-registering a client task after a reconnect while the old handle was never taken).","commonSituations":"Live adapter bugs where `connect()` is called twice; a client re-initialization path that re-spawns a heartbeat task; tests or custom adapters reusing one TaskSlot for sequential tasks without calling the take/cleanup method in between.","solutions":["Ensure the slot's existing task is stopped and its handle taken (via the slot's take/drop path) before calling insert again.","Fix the double-spawn: guard the client's spawn path so the task is started only once per slot (e.g. an `is_running`/once flag).","If replacing a task is intended, abort/detach the old handle explicitly with a different API rather than re-inserting into the occupied slot."],"exampleFix":"// before\nslot.insert(spawn_heartbeat()); // panics on reconnect because old handle still in slot\n\n// after\nif let Some(old) = slot.take() {\n    old.abort();\n}\nslot.insert(spawn_heartbeat());","handlingStrategy":"validation","validationCode":"// Rust: check the slot is free before inserting\nassert!(slot.is_empty(), \"task slot still owns a running task; take() it first\");\nslot.insert(handle);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat each TaskSlot as single-owner: always pair spawn+insert with take/abort cleanup","Guard client connect/initialize paths with a once flag so tasks cannot be spawned twice","In tests, cover reconnect and re-init flows to surface double-insert bugs early"],"tags":["rust","async","tokio","live-engine","panic"],"backgroundTag":"invalid-state-transition","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}