nautechsystems/nautilus_trader · error
submit second
Error message
submit second
What it means
Test panic from `.expect("submit second")` on the second `EventStoreWriter::submit`. Same `SubmitError` semantics as any submit: `Closed` if the writer/halt is terminal (possibly latched by the first submit stalling), `HaltSignaled` if this submit blocked past `halt_threshold`. Failure here means the writer degraded between the first and second entry.
Source
Thrown at crates/event_store/src/writer/mod.rs:1875
#[rstest]
fn record_snapshot_anchor_records_current_watermark_under_madsim() {
let (wrapper, shared) = SharedMemory::new();
shared
.lock()
.open_run(manifest("run-anchor"))
.expect("open");
let writer = EventStoreWriter::spawn(
Box::new(wrapper),
get_atomic_clock_static(),
noop_halt(),
WriterConfig::default(),
)
.expect("spawn");
writer.submit(entry_draft(10)).expect("submit first");
writer.submit(entry_draft(11)).expect("submit second");
let anchor = writer
.record_snapshot_anchor("cache://position-snapshots/P-1/0", "blake3:abc")
.expect("record anchor");
let backend = shared.lock();
assert_eq!(anchor.high_watermark, 2);
assert_eq!(
backend.latest_snapshot_anchor().expect("latest anchor"),
Some(anchor),
);
}
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Increase `WriterConfig::channel_capacity` so consecutive submits don't block on a full rendezvous channel.
- Raise `halt_threshold` above expected per-entry commit latency.
- Check whether the first submit or setup already fired a halt; once latched, submits always return `Closed`.
- Verify the writer thread is still alive (backend commits succeeding) between submits.
Example fix
// before
writer.submit(entry_draft(11)).expect("submit second");
// after
writer.submit(entry_draft(11))
.unwrap_or_else(|e| panic!("submit second failed: {e:?}")); Defensive patterns
Strategy: try-catch
Validate before calling
let in_flight = submitted_not_yet_acked; assert!(in_flight < channel_capacity, "avoid blocking submits on a full channel");
Type guard
fn is_stall_err(e: &SubmitError) -> Option<(std::time::Duration, std::time::Duration)> {
if let SubmitError::HaltSignaled { stalled_for, threshold } = e { Some((*stalled_for, *threshold)) } else { None }
} Try / catch
match writer.submit(draft) {
Err(SubmitError::HaltSignaled { stalled_for, threshold }) => {
log::error!("backpressure: stalled {stalled_for:?} > {threshold:?}");
}
other => other.map(|_| ()),
} Prevention
- Give channel_capacity headroom for burst submits.
- Track halt state: after any HaltSignaled, all later submits return Closed.
- Monitor commit latency to tune halt_threshold.
When it happens
Trigger: The first submit's stall fired the halt callback, latching `halted`, so the second submit returns `Closed`; channel capacity of 1 with a slow backend; writer thread exited after the first entry.
Common situations: Tiny `channel_capacity` plus simulated slow commits; halt threshold shorter than per-entry commit latency; a prior halt fired during setup making all submits fail.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- submit
- submit first
- first submit fits
- second submit must be buffered by the clamped capacity
- submit accepted
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/600c04a334804dba.
Report an issue: GitHub.