{"record":{"id":"600c04a334804dba","repo":"nautechsystems/nautilus_trader","slug":"submit-second","errorCode":null,"errorMessage":"submit second","messagePattern":"submit second","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/event_store/src/writer/mod.rs","lineNumber":1875,"sourceCode":"\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":1857,"sourceCodeEnd":1888,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/event_store/src/writer/mod.rs#L1857-L1888","documentation":"Test panic from `.expect(\"submit second\")` on the second `EventStoreWriter::submit`. Same `SubmitError` semantics as any submit: `Closed` if the writer/halt is terminal (possibly latched by the first submit stalling), `HaltSignaled` if this submit blocked past `halt_threshold`. Failure here means the writer degraded between the first and second entry.","triggerScenarios":"The first submit's stall fired the halt callback, latching `halted`, so the second submit returns `Closed`; channel capacity of 1 with a slow backend; writer thread exited after the first entry.","commonSituations":"Tiny `channel_capacity` plus simulated slow commits; halt threshold shorter than per-entry commit latency; a prior halt fired during setup making all submits fail.","solutions":["Increase `WriterConfig::channel_capacity` so consecutive submits don't block on a full rendezvous channel.","Raise `halt_threshold` above expected per-entry commit latency.","Check whether the first submit or setup already fired a halt; once latched, submits always return `Closed`.","Verify the writer thread is still alive (backend commits succeeding) between submits."],"exampleFix":"// before\nwriter.submit(entry_draft(11)).expect(\"submit second\");\n// after\nwriter.submit(entry_draft(11))\n    .unwrap_or_else(|e| panic!(\"submit second failed: {e:?}\"));","handlingStrategy":"try-catch","validationCode":"let in_flight = submitted_not_yet_acked;\nassert!(in_flight < channel_capacity, \"avoid blocking submits on a full channel\");","typeGuard":"fn is_stall_err(e: &SubmitError) -> Option<(std::time::Duration, std::time::Duration)> {\n    if let SubmitError::HaltSignaled { stalled_for, threshold } = e { Some((*stalled_for, *threshold)) } else { None }\n}","tryCatchPattern":"match writer.submit(draft) {\n    Err(SubmitError::HaltSignaled { stalled_for, threshold }) => {\n        log::error!(\"backpressure: stalled {stalled_for:?} > {threshold:?}\");\n    }\n    other => other.map(|_| ()),\n}","preventionTips":["Give channel_capacity headroom for burst submits.","Track halt state: after any HaltSignaled, all later submits return Closed.","Monitor commit latency to tune halt_threshold."],"tags":["rust","writer","backpressure","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"}