nautechsystems/nautilus_trader · error
owner present
Error message
owner present
What it means
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.
Source
Thrown at crates/adapters/derive/src/data.rs:2040
},
);
Some(generation)
}
fn attach_channel(&mut self, owner: ChannelOwner, generation: u64, channel: String) -> bool {
let Some(owned) = self.owners.get(&owner) else {
return false;
};
if owned.generation != generation {
return false;
}
if let Some(active_channel) = &owned.channel {
return active_channel == &channel;
}
self.owners.get_mut(&owner).expect("owner present").channel = Some(channel.clone());
self.channels.entry(channel).or_default().insert(owner);
true
}
fn is_current(&self, owner: ChannelOwner, generation: u64) -> bool {
self.owners
.get(&owner)
.is_some_and(|owned| owned.generation == generation)
}
fn is_current_channel(&self, owner: ChannelOwner, generation: u64, channel: &str) -> bool {
self.owners.get(&owner).is_some_and(|owned| {
owned.generation == generation && owned.channel.as_deref() == Some(channel)
})
}
fn remove_if_generation(
&mut self,View on GitHub (pinned to 18893faf8b)
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.
Example fix
// before
self.owners.get_mut(&owner).expect("owner present").channel = Some(channel.clone());
// after
if let Some(rec) = self.owners.get_mut(&owner) {
rec.channel = Some(channel.clone());
} else {
tracing::error!(?owner, "owner missing from registry at claim time");
return false;
} Defensive patterns
Strategy: validation
Validate before calling
debug_assert!(self.owners.contains_key(&owner), "owner {:?} must be registered before claiming", owner);
if !self.owners.contains_key(&owner) {
tracing::error!(?owner, "owner missing from registry");
return false;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- ticker channel present
- guarded above
- in-flight mutex poisoned
- wallet balance mutex poisoned
- instrument update lock poisoned
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4d7c7611818b5e2c.
Report an issue: GitHub.