stamparm/maltrail · error
just inserted
Error message
just inserted
What it means
Same invariant pattern in DnsTunneling::observe: after the saturation guard, a new Accumulator is inserted into self.pairs and immediately fetched with get_mut().expect("just inserted"). The expect encodes the guarantee that the key just inserted must be present; a panic indicates the map changed between insert and lookup.
Solutions
- Ensure insert and get_mut share the same lock scope with no intervening writes
- Use the entry() API so the fetch cannot miss
- Confirm the saturation guard returns before reaching the insert when pairs is full
Example fix
// before
self.pairs.insert(key.into(), Accumulator { first_sec: sec, ..Accumulator::default() });
self.pairs.get_mut(key).expect("just inserted")
// after
self.pairs.entry(key.into()).or_insert_with(|| Accumulator { first_sec: sec, ..Accumulator::default() }) Defensive patterns
Strategy: type-guard
Type guard
fn accumulator_mut<'m>(m: &'m mut HashMap<String, Accumulator>, k: &str, sec: u64) -> &'m mut Accumulator {
m.entry(k.to_owned()).or_insert_with(|| Accumulator { first_sec: sec, ..Accumulator::default() })
} Prevention
- Prefer the entry API for insert-or-fetch patterns
- Avoid intervening mutations between insert and use
- Add debug_assert!(m.contains_key(k)) after inserts during refactors
When it happens
Trigger: Concurrent or intervening mutation of self.pairs between insert and get_mut — e.g. a refactor inserting an eviction/clear call inside the locked region, or replacing the plain insert with logic that can skip insertion.
Common situations: Code changes to the observe() hot path (new eviction policies, per-key TTL sweeps) breaking the insert-then-get assumption; not reachable from ordinary DNS query patterns.
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
- just inserted
- [!] no VERSION constant found in
- [!] no maltrail-sensor package entry found in
- [!] not built - cargo build --release --manifest-path…
- invalid USERS entry ' ' [?] (hint: add whitespace at start…
AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13).
Data as JSON: /api/errors/0825032ea1e553e9.
Report an issue: GitHub.
Appendix: source
Thrown at sensor/src/heuristics/dns_tunneling.rs:207
/// Record one query and say whether the pair has just crossed every threshold.
///
/// `subdomain` is everything below the registered zone; `leading` is its first label.
pub fn observe(&mut self, key: &str, subdomain: &str, leading: &str, sec: u64) -> Outcome {
let carrying = leading.chars().count() >= settings::DNS_TUNNELING_MIN_LABEL
&& entropy_x100(leading) >= settings::DNS_TUNNELING_MIN_ENTROPY_X100;
let entry = match self.pairs.get_mut(key) {
Some(entry) => entry,
None => {
// Refuse rather than evict, like every other accumulator here: the key is chosen
// by whoever is sending, so eviction under flood would let them push their own
// earlier evidence out of the window.
if self.pairs.len() >= super::HEURISTIC_MAX_KEYS {
self.saturations += 1;
return Outcome::Quiet;
}
self.pairs.insert(key.into(), Accumulator { first_sec: sec, ..Accumulator::default() });
self.pairs.get_mut(key).expect("just inserted")
}
};
entry.queries += 1;
entry.last_sec = sec;
entry.bytes += subdomain.len();
if carrying {
entry.carrying += 1;
}
if entry.names.len() < super::HEURISTIC_MAX_KEYS {
entry.names.insert(subdomain.into());
}
if entry.alerted || !entry.verdict() {
return Outcome::Quiet;
}
entry.alerted = true;
Outcome::AlertView on GitHub (pinned to 77cfb06d76)