nautechsystems/nautilus_trader · error

first submit fits in channel before writer fail-stops

Error message

first submit fits in channel before writer fail-stops

What it means

Panic from `.expect("first submit fits in channel before writer fail-stops")` in `backend_disk_error_fires_halt_and_closes_writer`. The submit must be accepted into the channel (capacity 4) before the asynchronous disk failure fail-stops the writer; a rejected submit panics.

Source

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

        let (halt, captured) = captured_halt;
        let backend = DiskFailureBackend::default();

        let writer = EventStoreWriter::spawn(
            Box::new(backend),
            get_atomic_clock_static(),
            halt,
            WriterConfig {
                channel_capacity: 4,
                max_batch_entries: 1,
                max_batch_latency: Duration::from_millis(1),
                halt_threshold: Duration::from_millis(500),
            },
        )
        .expect("spawn");

        writer
            .submit(entry_draft(10))
            .expect("first submit fits in channel before writer fail-stops");

        // Wait until the writer fail-stops and the halt fires.
        let mut waited = Duration::ZERO;
        let deadline = Duration::from_millis(500);
        while captured.lock().is_empty() && waited < deadline {
            std::thread::sleep(Duration::from_millis(10));
            waited += Duration::from_millis(10);
        }

        let captured_reasons = captured.lock();
        assert!(matches!(
            captured_reasons.first(),
            Some(HaltReason::BackendDisk(_))
        ));
        drop(captured_reasons);

        // Subsequent submits return Closed once the writer thread has exited.
        let mut closed_seen = false;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Log the `SubmitError` variant to see whether it is Closed, HaltSignaled, or Full.
  2. Ensure the writer accepts submissions until the backend append actually fails.
  3. Verify the halt callback has not fired before the submit (the test waits for it afterwards).
  4. Fix submit/closed-state ordering so fail-stop happens after queued entries are accepted.

Example fix

// before
writer.submit(entry_draft(10)).expect("first submit fits in channel before writer fail-stops");
// after
writer.submit(entry_draft(10))
    .unwrap_or_else(|e| panic!("submit before fail-stop rejected: {e:?}"));
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm writer not halted/closed before submit
assert!(!writer.is_closed());

Try / catch

writer.submit(d).unwrap_or_else(|e| panic!("submit rejected: {e:?}"));

Prevention

When it happens

Trigger: `writer.submit(entry_draft(10))` returns `Err` before the backend's disk error is processed — the writer already halted/closed at startup, the channel is wrongly reported full, or the DiskFailureBackend triggers failure during submit rather than during append.

Common situations: A fail-stop path that closes the writer before the first queued entry lands, halt state set eagerly at spawn, or channel accounting marking capacity unavailable on an empty channel.

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/1a24dee7476b4338. Report an issue: GitHub.