nautechsystems/nautilus_trader · error

open

Error message

open

What it means

MemoryBackend::open_run initializes a run with the given manifest and is a precondition for spawning a writer that can commit entries. The expect at writer/mod.rs:1110 (test submit_signals_halt_when_stalled_past_threshold) panics if open_run returns Err. The library errors when the run cannot be opened, e.g. it is already open or the manifest is invalid.

Source

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

        }

        let final_hwm = writer.close(run_ended_draft()).expect("close");

        // 6 submits + 1 RunEnded == 7 entries, batch=2 -> 4 commits (3 size-driven + 1 close).
        assert_eq!(final_hwm, 7);
        assert_eq!(appends_seen.load(Ordering::SeqCst), 4);
    }

    #[rstest]
    fn submit_signals_halt_when_stalled_past_threshold(
        captured_halt: (HaltCallback, Arc<Mutex<Vec<HaltReason>>>),
    ) {
        // Channel capacity 1 with a backend gate held closed forces a stall: the first
        // submit fills the buffer, the writer thread blocks inside append_batch, and a
        // subsequent submit can never enqueue before the halt threshold fires.
        let (halt, captured) = captured_halt;
        let inner = Arc::new(Mutex::new(MemoryBackend::new()));
        inner.lock().open_run(manifest("run-halt")).expect("open");

        let gate = Arc::new((Mutex::new(false), parking_lot::Condvar::new()));
        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();

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use a fresh MemoryBackend per test so open_run is called exactly once per backend instance
  2. Inspect the EventStoreError from open_run — an 'already open' error means close/seal the prior run or discard the backend
  3. Validate the RunManifest fields before calling open_run
Defensive patterns

Strategy: validation

Validate before calling

let m = backend.manifest().map_err(|e| format!("cannot probe run state: {e}"))?;
if m.status != RunStatus::Open {
    backend.open_run(manifest("run-halt")).map_err(|e| format!("open_run failed: {e}"))?;
}

Type guard

fn run_openable(m: &RunManifest) -> bool {
    matches!(m.status, RunStatus::None | RunStatus::Ended | RunStatus::Sealed)
}

Try / catch

if let Err(e) = backend.open_run(manifest("run-halt")) {
    eprintln!("open_run failed: {e:?}");
}

Prevention

When it happens

Trigger: Calling inner.lock().open_run(manifest("run-halt")) on a MemoryBackend whose run is already open (double open), or with a manifest that fails validation, immediately before constructing a BlockingBackend for the halt-stall test.

Common situations: Reusing a shared MemoryBackend across tests without resetting it; setting up a gated backend for backpressure tests and forgetting the run is already open; invalid run manifest fields.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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