{"record":{"id":"4d7c7611818b5e2c","repo":"nautechsystems/nautilus_trader","slug":"owner-present","errorCode":null,"errorMessage":"owner present","messagePattern":"owner present","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/derive/src/data.rs","lineNumber":2040,"sourceCode":"            },\n        );\n        Some(generation)\n    }\n\n    fn attach_channel(&mut self, owner: ChannelOwner, generation: u64, channel: String) -> bool {\n        let Some(owned) = self.owners.get(&owner) else {\n            return false;\n        };\n\n        if owned.generation != generation {\n            return false;\n        }\n\n        if let Some(active_channel) = &owned.channel {\n            return active_channel == &channel;\n        }\n\n        self.owners.get_mut(&owner).expect(\"owner present\").channel = Some(channel.clone());\n        self.channels.entry(channel).or_default().insert(owner);\n        true\n    }\n\n    fn is_current(&self, owner: ChannelOwner, generation: u64) -> bool {\n        self.owners\n            .get(&owner)\n            .is_some_and(|owned| owned.generation == generation)\n    }\n\n    fn is_current_channel(&self, owner: ChannelOwner, generation: u64, channel: &str) -> bool {\n        self.owners.get(&owner).is_some_and(|owned| {\n            owned.generation == generation && owned.channel.as_deref() == Some(channel)\n        })\n    }\n\n    fn remove_if_generation(\n        &mut self,","sourceCodeStart":2022,"sourceCodeEnd":2058,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/derive/src/data.rs#L2022-L2058","documentation":"When claiming ownership of an unowned channel, the adapter looks up the owner in `self.owners` and sets its channel. This `expect(\"owner present\")` fires if the owner key is missing from the map at that point — the function assumes the earlier lookup that produced `owned` already guaranteed the entry exists. Reaching the panic means internal state was mutated between the check and the insert, or a new owner was passed without being registered first.","triggerScenarios":"Calling the channel-claim function with a `ChannelOwner` that was never inserted into `self.owners` (e.g. a newly constructed owner value not present in the map), or concurrent mutation of `owners` invalidating the earlier existence check.","commonSituations":"Hit during adapter development when adding new ChannelOwner variants or subscription kinds and forgetting to insert them into the owners map in the earlier code path; also after refactors that change how `owned` is derived.","solutions":["Ensure every owner passed to the claim function is inserted into `self.owners` (with its generation) before the channel-assignment branch.","Use the entry API (`self.owners.entry(owner)`) so the insert and update are one atomic step instead of relying on the earlier check.","If concurrency is possible, hold the borrow/mutex across the check and mutation.","Add a debug_assert for owner presence with context about which owner was missing."],"exampleFix":"// before\nself.owners.get_mut(&owner).expect(\"owner present\").channel = Some(channel.clone());\n// after\nif let Some(rec) = self.owners.get_mut(&owner) {\n    rec.channel = Some(channel.clone());\n} else {\n    tracing::error!(?owner, \"owner missing from registry at claim time\");\n    return false;\n}","handlingStrategy":"validation","validationCode":"debug_assert!(self.owners.contains_key(&owner), \"owner {:?} must be registered before claiming\", owner);\nif !self.owners.contains_key(&owner) {\n    tracing::error!(?owner, \"owner missing from registry\");\n    return false;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Insert every owner into self.owners before channel assignment","Use self.owners.entry(owner) to combine check and mutation","Re-run existence checks after any code that can remove owners"],"tags":["rust","panic","internal-invariant","map-lookup"],"backgroundTag":"internal-invariant-violation","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"}