nautechsystems/nautilus_trader · error

spawn

Error message

spawn

What it means

EventStoreWriter::spawn starts the background writer thread that drains the submit channel and commits batches to the backend. The expect at writer/mod.rs:1131 (test submit_signals_halt_when_stalled_past_threshold) panics if spawn fails. Spawn errors when the run/backend is not in an open, writable state, so the thread could not be started safely.

Source

Thrown at crates/event_store/src/writer/mod.rs:1131

        let appends_seen = Arc::new(AtomicUsize::new(0));
        let backend = BlockingBackend::new(
            Arc::clone(&inner),
            Arc::clone(&gate),
            Arc::clone(&appends_seen),
        );

        let halt_threshold = Duration::from_millis(50);
        let config = WriterConfig {
            channel_capacity: 1,
            max_batch_entries: 1,
            max_batch_latency: Duration::from_millis(1),
            halt_threshold,
        };

        let clock = get_atomic_clock_static();
        let boxed = Box::new(backend);

        let writer = EventStoreWriter::spawn(boxed, clock, halt, config).expect("spawn");

        // First submit fits in the channel; the writer thread takes it and blocks.
        writer.submit(entry_draft(10)).expect("first submit fits");

        // Wait long enough for the writer to dequeue and become blocked at the gate.
        std::thread::sleep(Duration::from_millis(20));

        // Second and third submits saturate the slot; the channel buffer holds one,
        // the next one stalls past the halt threshold.
        let _ = writer.submit(entry_draft(11));
        let stalled = writer.submit(entry_draft(12)).expect_err("must stall");

        match stalled {
            SubmitError::HaltSignaled { .. } => {}
            SubmitError::Closed => panic!("expected HaltSignaled, was Closed"),
        }
        let captured_reasons = captured.lock();
        assert_eq!(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Call backend.open_run(manifest(...)) before EventStoreWriter::spawn and check its Result
  2. Ensure the backend's manifest()/high_watermark() return Ok during initialization
  3. Confirm the run status is Open, not already Sealed/Ended
  4. Validate WriterConfig (channel_capacity, thresholds) before spawn

Example fix

// before
let writer = EventStoreWriter::spawn(boxed, clock, halt, config).expect("spawn");
// after
let writer = EventStoreWriter::spawn(boxed, clock, halt, config)
    .unwrap_or_else(|e| panic!("writer spawn failed: {e:?}"));
Defensive patterns

Strategy: validation

Validate before calling

let m = backend.manifest().map_err(|e| format!("backend init query failed: {e}"))?;
assert_eq!(m.status, RunStatus::Open, "spawn requires an open run");

Type guard

fn can_spawn_writer(m: &RunManifest) -> bool {
    m.status == RunStatus::Open
}

Try / catch

match EventStoreWriter::spawn(boxed, clock, halt, config) {
    Ok(writer) => { /* use writer */ }
    Err(e) => eprintln!("spawn failed: {e:?}"),
}

Prevention

When it happens

Trigger: Calling EventStoreWriter::spawn(boxed, clock, halt, config) with a backend whose run was never opened, a backend that fails initialization (manifest/high_watermark calls error), or invalid WriterConfig values.

Common situations: Constructing a writer for halt-threshold tests with channel_capacity=1 and a gated backend before opening the run; passing a failing backend (e.g. manifest() -> Err(Backend("disk failure"))) to spawn; reusing a backend whose run is already sealed.

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/a81f633f2aeb24f8. Report an issue: GitHub.