nautechsystems/nautilus_trader · error
Replacement scan verification evidence is incomplete
Error message
Replacement scan verification evidence is incomplete
What it means
record_execution_replacement_scan validates that the scan carries complete verification evidence: at least one decision, exactly 3 provider IDs, exactly 3 operator IDs, and at least 3 failure domain IDs. If any of these invariants is unmet, the scan is rejected before any database writes.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:6238
.context("Replacement scan cursor timestamp is negative")?,
base_fee_per_gas: base_fee
.map(|value| {
value.parse::<u128>().map_err(|_| {
anyhow::anyhow!("Replacement scan cursor base fee is invalid")
})
})
.transpose()?,
})
},
)
.transpose()
}
pub(crate) async fn record_execution_replacement_scan(
&self,
scan: &ExecutionReplacementScan<'_>,
) -> anyhow::Result<()> {
anyhow::ensure!(
!scan.decisions.is_empty()
&& scan.provider_ids.len() == 3
&& scan.operator_ids.len() == 3
&& scan.failure_domain_ids.len() >= 3,
"Replacement scan verification evidence is incomplete"
);
let chain_id = i32::try_from(scan.chain_id)
.context("Replacement scan chain ID exceeds PostgreSQL INTEGER")?;
let nonce = i64::try_from(scan.nonce)
.context("Replacement scan nonce exceeds PostgreSQL BIGINT")?;
let mut transaction = self
.pool
.begin()
.await
.context("failed to start verified replacement scan transition")?;
let (stored_version, stored_digest, stored_nonce, revision) =
sqlx::query_as::<_, (String, String, i64, i64)>(
"View on GitHub (pinned to 18893faf8b)
Solutions
- Populate provider_ids and operator_ids with the 3 configured identities and at least 3 failure domain IDs before calling
- Ensure at least one verification decision is collected into scan.decisions
- Fix the upstream discovery/aggregation step that produced incomplete identity sets
- Assert scan completeness at construction time to fail early
Example fix
// before
let scan = ExecutionReplacementScan { decisions: vec![], provider_ids: p, operator_ids: o, failure_domain_ids: f, .. };
// after
assert_eq!(p.len(), 3, "provider_ids");
assert_eq!(o.len(), 3, "operator_ids");
assert!(f.len() >= 3, "failure_domain_ids");
assert!(!decisions.is_empty(), "decisions");
let scan = ExecutionReplacementScan { decisions, provider_ids: p, operator_ids: o, failure_domain_ids: f, .. }; Defensive patterns
Strategy: validation
Validate before calling
fn scan_evidence_complete(scan: &ExecutionReplacementScan) -> bool {
!scan.decisions.is_empty()
&& scan.provider_ids.len() == 3
&& scan.operator_ids.len() == 3
&& scan.failure_domain_ids.len() >= 3
}
anyhow::ensure!(scan_evidence_complete(&scan), "scan evidence incomplete"); Type guard
fn is_complete_scan(scan: &ExecutionReplacementScan) -> bool {
scan.decisions.len() > 0
&& scan.provider_ids.len() == 3
&& scan.operator_ids.len() == 3
&& scan.failure_domain_ids.len() >= 3
} Try / catch
if let Err(e) = db.record_execution_replacement_scan(&scan).await {
if e.to_string().contains("evidence is incomplete") {
// fix scan construction; this is a caller bug, not retryable
return Err(anyhow::anyhow!("refusing to record scan: {e}"));
}
return Err(e);
} Prevention
- Validate scan structs at construction, before I/O
- Assert identity counts come from the configured provider/operator set
- Never drop all decisions during filtering; reject instead
- Unit-test scan builders against the completeness invariants
When it happens
Trigger: Calling record_execution_replacement_scan with an ExecutionReplacementScan where decisions is empty, provider_ids.len() != 3, operator_ids.len() != 3, or failure_domain_ids.len() < 3.
Common situations: Constructing the scan struct with default/empty collections; a provider/operator discovery step returning fewer identities than configured; filtering decisions out before recording, leaving an empty batch.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/13f24b056742a1a4.
Report an issue: GitHub.