nautechsystems/nautilus_trader · error · anyhow::Error
Connect verification evidence is incomplete
Error message
Connect verification evidence is incomplete
What it means
`ensure_execution_verification_schema` requires the bootstrap's connect-verification evidence to be complete: exactly 3 provider IDs, exactly 3 operator IDs, at least 3 failure-domain IDs, and at least one recorded decision. This `anyhow::ensure!` fires when any of those conditions is unmet, meaning the quorum evidence backing the verification ledger is missing or insufficient. The schema's own CHECK constraints (`cardinality(provider_ids) = 3`, etc.) mirror this requirement, so incomplete evidence would be rejected downstream anyway.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:3876
///
/// Returns an error if the schema, migration snapshot, historical reconstruction, or retained
/// evidence is inconsistent, or persistence fails.
pub(crate) async fn ensure_execution_verification_schema(
&self,
bootstrap: &ExecutionVerificationBootstrap<'_>,
) -> anyhow::Result<()> {
let first_header = bootstrap
.finalized_headers
.first()
.ok_or_else(|| anyhow::anyhow!("Verified finalized header ledger is empty"))?;
anyhow::ensure!(
bootstrap.finalized_headers.windows(2).all(|headers| {
headers[1].number == headers[0].number.saturating_add(1)
&& headers[1].parent_hash == headers[0].hash
}),
"Verified finalized headers are not one continuous parent-linked chain"
);
anyhow::ensure!(
bootstrap.provider_ids.len() == 3
&& bootstrap.operator_ids.len() == 3
&& bootstrap.failure_domain_ids.len() >= 3
&& !bootstrap.decisions.is_empty(),
"Connect verification evidence is incomplete"
);
let chain_id = i32::try_from(bootstrap.chain_id)
.context("Verification chain ID exceeds PostgreSQL INTEGER")?;
let checkpoint_number = i64::try_from(bootstrap.checkpoint_number)
.context("Verification checkpoint exceeds PostgreSQL BIGINT")?;
let checkpoint_timestamp = i64::try_from(bootstrap.checkpoint_timestamp)
.context("Verification checkpoint timestamp exceeds PostgreSQL BIGINT")?;
let next_canonical_nonce = i64::try_from(bootstrap.next_canonical_nonce)
.context("Canonical nonce exceeds PostgreSQL BIGINT")?;
let observed_canonical_nonce = i64::try_from(bootstrap.observed_canonical_nonce)
.context("Observed canonical nonce exceeds PostgreSQL BIGINT")?;
let base_fee = bootstrap
.checkpoint_base_fee_per_gasView on GitHub (pinned to 18893faf8b)
Solutions
- Ensure exactly three providers and three operators are configured and reachable, with at least three distinct failure domains, before building the bootstrap.
- Complete the connect-verification flow so at least one decision is recorded before invoking `ensure_execution_verification_schema`.
- Check provider connectivity — if fewer than three providers respond, the quorum evidence will be short and this error fires.
- Review how provider/operator/failure-domain IDs are aggregated into the bootstrap; a filtering bug can silently drop entries below the required counts.
Example fix
// before
let bootstrap = ExecutionVerificationBootstrap {
provider_ids: &responded_providers, // maybe only 2 responded
operator_ids: &operators,
failure_domain_ids: &domains,
decisions: &decisions,
..b
};
// after
anyhow::ensure!(
responded_providers.len() == 3
&& operators.len() == 3
&& domains.len() >= 3
&& !decisions.is_empty(),
"connect verification evidence incomplete before migration"
);
let bootstrap = ExecutionVerificationBootstrap {
provider_ids: &responded_providers,
operator_ids: &operators,
failure_domain_ids: &domains,
decisions: &decisions,
..b
}; Defensive patterns
Strategy: validation
Validate before calling
fn validate_connect_evidence(b: &ExecutionVerificationBootstrap<'_>) -> Result<(), String> {
match (
b.provider_ids.len() == 3,
b.operator_ids.len() == 3,
b.failure_domain_ids.len() >= 3,
!b.decisions.is_empty(),
) {
(true, true, true, true) => Ok(()),
(p, o, f, d) => Err(format!(
"incomplete evidence: providers={} (need 3), operators={} (need 3), failure_domains>=3={}, decisions_nonempty={}",
b.provider_ids.len(), b.operator_ids.len(), f, d
)),
}
} Type guard
fn has_complete_connect_evidence(b: &ExecutionVerificationBootstrap<'_>) -> bool {
b.provider_ids.len() == 3
&& b.operator_ids.len() == 3
&& b.failure_domain_ids.len() >= 3
&& !b.decisions.is_empty()
} Try / catch
match database.ensure_execution_verification_schema(&bootstrap).await {
Err(e) if e.to_string().contains("Connect verification evidence is incomplete") => {
// check provider/operator configuration and connect-verification completion, rebuild evidence, retry
}
Err(e) => return Err(e),
Ok(()) => {}
} Prevention
- Configure exactly three providers and three operators; validate the config at load time.
- Gate migration on connect-verification completion — do not run it before at least one decision is recorded.
- Health-check all providers before bootstrap so quorum evidence is never short due to unreachable endpoints.
- Log provider/operator/failure-domain counts during bootstrap assembly to catch filtering bugs early.
When it happens
Trigger: Constructing `ExecutionVerificationBootstrap` where `provider_ids.len() != 3`, `operator_ids.len() != 3`, `failure_domain_ids.len() < 3`, or `decisions.is_empty()` — e.g. only one or two providers responded during connect verification, or no decisions were recorded before migration.
Common situations: A misconfigured provider list (fewer than 3 RPC endpoints); providers being unreachable during connect verification so quorum never completes; an operator/failure-domain topology not yet fully registered; running migration before any connect-verification decisions have been persisted.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Verified nonce assignment requires exactly three provider an
- Verified action requires the configured provider identities
- Chain ID mismatch at connect: expected {expected_chain_id},
- Unsupported blockchain {blockchain} for RPC connection
- Invalid venue {}, expected Blockchain DEX format
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a34632ba0f93456f.
Report an issue: GitHub.