nautechsystems/nautilus_trader · error
record anchor
Error message
record anchor
What it means
Test panic from `.expect("record anchor")` on `EventStoreWriter::record_snapshot_anchor`, which returns `EventStoreError::Closed` if halted/shut down, a Backend stall error if enqueue or the ack round-trip exceeds `halt_threshold`, or a backend error while persisting the anchor. The method flushes pending entries first, then records the anchor at the durable high-watermark so it never points past committed state.
Source
Thrown at crates/event_store/src/writer/mod.rs:1878
let (wrapper, shared) = SharedMemory::new();
shared
.lock()
.open_run(manifest("run-anchor"))
.expect("open");
let writer = EventStoreWriter::spawn(
Box::new(wrapper),
get_atomic_clock_static(),
noop_halt(),
WriterConfig::default(),
)
.expect("spawn");
writer.submit(entry_draft(10)).expect("submit first");
writer.submit(entry_draft(11)).expect("submit second");
let anchor = writer
.record_snapshot_anchor("cache://position-snapshots/P-1/0", "blake3:abc")
.expect("record anchor");
let backend = shared.lock();
assert_eq!(anchor.high_watermark, 2);
assert_eq!(
backend.latest_snapshot_anchor().expect("latest anchor"),
Some(anchor),
);
}
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure no halt was fired and the writer is still open before calling `record_snapshot_anchor`.
- Increase `halt_threshold` if flushing pending entries legitimately needs longer than the ack timeout.
- Check the returned `EventStoreError` string ("stalled", "ack channel disconnected", backend error) to locate the failing stage.
- Verify the backend's anchor persistence path (e.g. `record_snapshot_anchor` implementation) succeeds for the given blob_ref.
Example fix
// before
let anchor = writer.record_snapshot_anchor("cache://position-snapshots/P-1/0", "blake3:abc")
.expect("record anchor");
// after
let anchor = writer.record_snapshot_anchor("cache://position-snapshots/P-1/0", "blake3:abc")
.unwrap_or_else(|e| panic!("record anchor failed: {e:?}")); Defensive patterns
Strategy: retry
Validate before calling
if halted.load(Ordering::Acquire) { return Err(EventStoreError::Closed); }
// ensure no outstanding submits likely to exceed halt_threshold before anchoring Try / catch
match writer.record_snapshot_anchor(blob_ref, hash) {
Ok(anchor) => cache.store(anchor),
Err(EventStoreError::Closed) => log::warn!("writer halted/closed; anchor skipped"),
Err(e) => return Err(e),
} Prevention
- Record anchors only while the writer is healthy and unhalted.
- Keep halt_threshold larger than worst-case flush + ack latency.
- Inspect the error text to distinguish enqueue stall vs ack timeout vs backend write failure.
When it happens
Trigger: Calling after a halt fired or the writer closed; the ack channel timing out because the writer thread cannot commit pending entries within `halt_threshold`; the ack channel disconnecting (writer thread died); the backend rejecting the anchor write.
Common situations: Recording an anchor while earlier submits are still pending and the backend is slow; calling on a halted writer; anchor blob_ref/content_hash handling triggering a backend persistence error.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- position snapshot frame {snapshot_index} for {position_id} a
- position snapshot blob_ref {blob_ref} skips missing frame {}
- position snapshot id {} does not match blob_ref position {po
- record snapshot anchor: {e}
- Failed to decode position replay state: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d5e3b71fefc7b6aa.
Report an issue: GitHub.