{"record":{"id":"f411e31424005808","repo":"nautechsystems/nautilus_trader","slug":"submit-first","errorCode":null,"errorMessage":"submit first","messagePattern":"submit first","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/event_store/src/writer/mod.rs","lineNumber":1874,"sourceCode":"    }\n\n    #[rstest]\n    fn record_snapshot_anchor_records_current_watermark_under_madsim() {\n        let (wrapper, shared) = SharedMemory::new();\n        shared\n            .lock()\n            .open_run(manifest(\"run-anchor\"))\n            .expect(\"open\");\n\n        let writer = EventStoreWriter::spawn(\n            Box::new(wrapper),\n            get_atomic_clock_static(),\n            noop_halt(),\n            WriterConfig::default(),\n        )\n        .expect(\"spawn\");\n\n        writer.submit(entry_draft(10)).expect(\"submit first\");\n        writer.submit(entry_draft(11)).expect(\"submit second\");\n        let anchor = writer\n            .record_snapshot_anchor(\"cache://position-snapshots/P-1/0\", \"blake3:abc\")\n            .expect(\"record anchor\");\n\n        let backend = shared.lock();\n        assert_eq!(anchor.high_watermark, 2);\n        assert_eq!(\n            backend.latest_snapshot_anchor().expect(\"latest anchor\"),\n            Some(anchor),\n        );\n    }\n}\n","sourceCodeStart":1856,"sourceCodeEnd":1888,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/event_store/src/writer/mod.rs#L1856-L1888","documentation":"Test panic from `.expect(\"submit first\")` on the first `EventStoreWriter::submit`, which returns `SubmitError::Closed` (writer shut down, thread exited, or prior halt latched) or `SubmitError::HaltSignaled` (channel full longer than `halt_threshold`). Under madsim, thread/timing semantics differ, making writer-thread liveness the usual failure point.","triggerScenarios":"Submitting immediately after spawn when the writer thread failed to start; a halt already latched from setup; the bounded channel never draining because the writer thread is dead, blocking until `halt_threshold`.","commonSituations":"madsim test runs where thread spawn/scheduling behaves differently; halt threshold set too low relative to simulated commit latency; backend without an open run killing the writer thread at startup.","solutions":["Confirm `spawn` succeeded on a backend with an open run before the first submit.","Under madsim, ensure the writer thread can run (check madsim thread model compatibility of the batcher loop).","Raise `halt_threshold` if simulated latency legitimately exceeds it.","Inspect the `SubmitError` variant to distinguish `Closed` from `HaltSignaled`."],"exampleFix":"// before\nwriter.submit(entry_draft(10)).expect(\"submit first\");\n// after\nwriter.submit(entry_draft(10))\n    .unwrap_or_else(|e| panic!(\"submit first failed: {e:?}\"));","handlingStrategy":"retry","validationCode":"if halted.load(Ordering::Acquire) { return Err(anyhow!(\"writer halted\")); }","typeGuard":"fn is_closed(e: &SubmitError) -> bool { matches!(e, SubmitError::Closed) }","tryCatchPattern":"if let Err(SubmitError::Closed) = writer.submit(draft) {\n    log::warn!(\"writer closed; re-spawn required before further submits\");\n}","preventionTips":["Spawn on a backend with an open run so the writer thread survives.","Under madsim, validate thread/scheduling assumptions early with a smoke submit.","Set halt_threshold above simulated commit latency."],"tags":["rust","writer","madsim","submit"],"backgroundTag":"invalid-state-transition","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}