nautechsystems/nautilus_trader · error
submit
Error message
submit
What it means
This is a test panic from `.expect("submit")` on `EventStoreWriter::submit`, which returns `SubmitError` on failure. The library returns `SubmitError::Closed` when the writer is shut down, the writer thread has exited, or a prior halt already fired (halt is terminal for the run), and `SubmitError::HaltSignaled` when the submit blocked longer than the configured `halt_threshold` due to backpressure. In this latency-window test, a stall past the 30s halt threshold or an unexpected writer shutdown panics.
Source
Thrown at crates/event_store/src/writer/mod.rs:1686
// surface at close drain, masking the steady-state batching contract.
let (halt, _) = captured_halt;
let (wrapper, shared) = SharedMemory::new();
shared.lock().open_run(manifest("run-time")).expect("open");
let writer = EventStoreWriter::spawn(
Box::new(wrapper),
get_atomic_clock_static(),
halt,
WriterConfig {
channel_capacity: 32,
max_batch_entries: 100,
max_batch_latency: Duration::from_millis(20),
halt_threshold: Duration::from_secs(30),
},
)
.expect("spawn");
writer.submit(entry_draft(10)).expect("submit");
// Wait long enough that the latency window has elapsed multiple times.
let mut waited = Duration::ZERO;
while writer.high_watermark() == 0 && waited < Duration::from_millis(500) {
std::thread::sleep(Duration::from_millis(5));
waited += Duration::from_millis(5);
}
assert_eq!(
writer.high_watermark(),
1,
"latency window must commit a sub-batch entry before close",
);
let final_hwm = writer.close(run_ended_draft()).expect("close");
assert_eq!(final_hwm, 2);
}
#[rstest]View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure the backend has an open run before `EventStoreWriter::spawn` and that `append_batch` can commit promptly.
- Increase `WriterConfig::halt_threshold` or `channel_capacity` if legitimate bursts cause backpressure stalls.
- Never call `submit` after a halt fired or after `close`; check `high_watermark()`/halt state first.
- Match on the returned `SubmitError` (`Closed` vs `HaltSignaled`) and log `stalled_for`/`threshold` to identify which path fired.
Example fix
// before
writer.submit(entry_draft(10)).expect("submit");
// after
match writer.submit(entry_draft(10)) {
Ok(()) => {}
Err(SubmitError::Closed) => panic!("writer closed/halted before submit"),
Err(SubmitError::HaltSignaled { stalled_for, threshold }) => {
panic!("submit stalled {stalled_for:?} > {threshold:?}")
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// before submitting
if writer_halted.load(Ordering::Acquire) { return; }
assert!(backend_has_open_run, "open_run must precede writer spawn"); Type guard
fn is_halt_signaled(e: &SubmitError) -> bool { matches!(e, SubmitError::HaltSignaled { .. }) } Try / catch
match writer.submit(draft) {
Ok(()) => {}
Err(SubmitError::Closed) => log::warn!("writer closed; dropping entry"),
Err(SubmitError::HaltSignaled { stalled_for, threshold }) => {
log::error!("submit stalled {stalled_for:?} > {threshold:?}; halting run");
}
} Prevention
- Always open a run on the backend before spawning the writer.
- Size channel_capacity and halt_threshold above worst-case commit latency.
- Treat a fired halt as terminal: never submit afterwards.
- Log SubmitError variants to distinguish closed vs stalled paths.
When it happens
Trigger: Calling `submit` after the writer thread exited or a halt was signaled; the entry channel staying full past `WriterConfig::halt_threshold` (e.g. backend `append_batch` commits stall longer than 30s); calling submit after `close` or after another submit stalled.
Common situations: A slow or blocked backend making the bounded channel back up; reusing a writer after a halt was latched by an earlier stall; tests with artificially tiny `max_batch_latency`/`halt_threshold` configs; spawning without an open run so the writer thread dies immediately.
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 second
- first submit fits
- second submit must be buffered by the clamped capacity
- submit accepted
- second submit fills the slot
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/bc5c9761384b915c.
Report an issue: GitHub.