{"record":{"id":"e0cd378376e5e480","repo":"nautechsystems/nautilus_trader","slug":"close","errorCode":null,"errorMessage":"close","messagePattern":"close","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/event_store/src/writer/mod.rs","lineNumber":1094,"sourceCode":"        );\n\n        let config = WriterConfig {\n            channel_capacity: 16,\n            max_batch_entries: 2,\n            max_batch_latency: Duration::from_secs(30),\n            halt_threshold: Duration::from_secs(30),\n        };\n\n        let clock = get_atomic_clock_static();\n        let boxed = Box::new(backend);\n\n        let writer = EventStoreWriter::spawn(boxed, clock, halt, config).expect(\"spawn\");\n\n        for ts in 10_u64..16_u64 {\n            writer.submit(entry_draft(ts)).expect(\"submit\");\n        }\n\n        let final_hwm = writer.close(run_ended_draft()).expect(\"close\");\n\n        // 6 submits + 1 RunEnded == 7 entries, batch=2 -> 4 commits (3 size-driven + 1 close).\n        assert_eq!(final_hwm, 7);\n        assert_eq!(appends_seen.load(Ordering::SeqCst), 4);\n    }\n\n    #[rstest]\n    fn submit_signals_halt_when_stalled_past_threshold(\n        captured_halt: (HaltCallback, Arc<Mutex<Vec<HaltReason>>>),\n    ) {\n        // Channel capacity 1 with a backend gate held closed forces a stall: the first\n        // submit fills the buffer, the writer thread blocks inside append_batch, and a\n        // subsequent submit can never enqueue before the halt threshold fires.\n        let (halt, captured) = captured_halt;\n        let inner = Arc::new(Mutex::new(MemoryBackend::new()));\n        inner.lock().open_run(manifest(\"run-halt\")).expect(\"open\");\n\n        let gate = Arc::new((Mutex::new(false), parking_lot::Condvar::new()));","sourceCodeStart":1076,"sourceCodeEnd":1112,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/event_store/src/writer/mod.rs#L1076-L1112","documentation":"EventStoreWriter::close flushes pending entries, writes the RunEnded entry, seals the run, and returns the final high watermark. This expect fires when close returns Err, e.g. the backend fails the final append, manifest update, or seal during shutdown. In this test suite it guards the batch-threshold test's expected final watermark of 7.","triggerScenarios":"Calling writer.close(run_ended_draft()) when the backend's append_batch fails (disk error, backend error like the FailingBackend's \"disk failure\"), when the run was never opened, or when the writer thread already halted due to backpressure/disk failure so the close entry cannot be committed.","commonSituations":"Tests exercising batch thresholds (max_batch_entries=2) with six submits plus RunEnded; shutdown paths where the underlying storage backend reports disk failure; closing a writer whose run is already sealed.","solutions":["Inspect the EventStoreError returned inside close (e.g. Backend(\"disk failure\")) and fix the backend failure before closing","Ensure open_run was called on the backend before spawning the writer and submitting entries","Check that the writer was not already halted (see halt callback captures) — halt latches make close fail after a stall or disk error","Verify the run is not already sealed/ended; sealing twice is an invalid state transition"],"exampleFix":"// before\nlet final_hwm = writer.close(run_ended_draft()).expect(\"close\");\n// after\nlet final_hwm = writer\n    .close(run_ended_draft())\n    .unwrap_or_else(|e| panic!(\"writer close failed: {e:?}\"));","handlingStrategy":"try-catch","validationCode":"let m = backend.manifest().map_err(|e| format!(\"backend unhealthy before close: {e}\"))?;\nassert_eq!(m.status, RunStatus::Open, \"run must be open before close\");","typeGuard":"fn writer_closeable(m: &RunManifest) -> bool {\n    m.status == RunStatus::Open\n}","tryCatchPattern":"match writer.close(run_ended_draft()) {\n    Ok(hwm) => println!(\"sealed at hwm {hwm}\"),\n    Err(EventStoreError::Backend(msg)) => eprintln!(\"backend failure on close: {msg}\"),\n    Err(e) => eprintln!(\"close failed: {e:?}\"),\n}","preventionTips":["Always open_run before spawning a writer and check every Result","Monitor the halt callback; once a halt fires, close will fail","Never seal or end a run twice","Test shutdown paths against failing backends deliberately"],"tags":["rust","panic","event-store","test-assertion"],"backgroundTag":"database-write-failed","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"}