nautechsystems/nautilus_trader · error
position snapshot id {} does not match blob_ref position {po
Error message
position snapshot id {} does not match blob_ref position {position_id} What it means
decode_position_snapshot_blob deserializes a JSON Position snapshot and verifies its 'id' has the form '<position_id>-<uuid4>'. This error means the snapshot's id does not start with the position id from the blob_ref, so the blob belongs to a different position than the ref claims.
Source
Thrown at crates/common/src/cache/position.rs:472
anyhow::bail!("position snapshot blob_ref {blob_ref} has empty position id");
}
let snapshot_index = snapshot_index.parse::<usize>().map_err(|e| {
anyhow::anyhow!("position snapshot blob_ref {blob_ref} has invalid frame index: {e}")
})?;
Ok((PositionId::new(position_id), snapshot_index))
}
fn decode_position_snapshot_blob(
position_id: &PositionId,
blob: &[u8],
) -> anyhow::Result<Position> {
let snapshot = serde_json::from_slice::<Position>(blob)?;
let expected_prefix = format!("{}-", position_id.as_str());
let Some(snapshot_uuid) = snapshot.id.as_str().strip_prefix(&expected_prefix) else {
anyhow::bail!(
"position snapshot id {} does not match blob_ref position {position_id}",
snapshot.id
);
};
if UUID4::from_str(snapshot_uuid).is_err() {
anyhow::bail!(
"position snapshot id {} does not match blob_ref position {position_id}",
snapshot.id
);
}
Ok(snapshot)
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the blob_ref and blob are a matched pair from the same write (same position)
- Re-export the snapshot so the ref and blob are regenerated together
- Check that external storage didn't reorder or re-key blobs relative to their refs
Defensive patterns
Strategy: validation
Validate before calling
let snapshot: Position = serde_json::from_slice(&blob)?;
if !snapshot.id.as_str().starts_with(&format!("{position_id}-")) {
return Err(anyhow!("blob does not belong to position {position_id}"));
} Type guard
fn blob_matches_position(snapshot_id: &str, position_id: &PositionId) -> bool {
snapshot_id.starts_with(&format!("{}-", position_id.as_str()))
} Try / catch
match cache.restore_snapshot_blob(&blob_ref, &blob) {
Err(e) if e.to_string().contains("does not match blob_ref position") => {
// ref/blob pair is inconsistent: re-fetch or re-export the snapshot
}
other => other?,
} Prevention
- Store ref and blob atomically as one record so they can't desynchronize
- Never hand-edit or rewrite blob_refs when moving snapshots between storage backends
When it happens
Trigger: restore_snapshot_blob called with a (blob_ref, blob) pair that was mismatched — e.g. the blob stored under one position's ref actually contains another position's snapshot, or the position_id parsed from the ref was altered.
Common situations: Ref and blob stored/transported out of sync in external storage; hand-editing blob_refs; a cache backend that re-keyed blobs; version changes to the '<id>-<uuid>' snapshot id format.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- DataActor {} must be registered before calling `cache()` - t
- Order {client_order_id} not found
- Position {position_id} not found
- Order for {} not found to determine position ID
- Order {client_order_id} not found in cache.
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/31f52e2356d6309d.
Report an issue: GitHub.