affaan-m/ECC · error · anyhow::Error
incomplete harness health evidence integrity metadata
Error message
incomplete harness health evidence integrity metadata
What it means
An audit entry's four health-evidence fields are partially populated (some NULL, some not). The integrity model requires them to be all-present or all-absent together; a partial set cannot be verified and indicates a malformed write.
Source
Thrown at ecc2/src/session/store.rs:5596
let fields = (
&entry.health_evidence_json,
&entry.health_evidence_sha256,
entry.asserted_health,
&entry.health_check_status,
);
if matches!(fields, (None, None, None, None)) {
if entry.legacy_unverifiable
|| matches!(
entry.event_type.as_str(),
"initial_activation" | "promotion_rejected"
)
{
return Ok(());
}
anyhow::bail!("missing harness health evidence integrity metadata");
}
let (Some(json), Some(digest), Some(asserted), Some(status)) = fields else {
anyhow::bail!("incomplete harness health evidence integrity metadata");
};
if json.len() > 8192 {
anyhow::bail!("harness health evidence exceeds integrity verification bound");
}
let snapshot: HealthEvidenceSnapshot = serde_json::from_str(json)?;
let snapshot_candidate_id =
Self::resolve_harness_candidate_id(&self.conn, &snapshot.candidate_id)?;
if snapshot.canonical_json()? != *json
|| snapshot.digest()? != *digest
|| snapshot.asserted_healthy != asserted
|| snapshot_candidate_id != entry.candidate_id
{
anyhow::bail!("harness health evidence integrity verification failed");
}
let event_consistent = match entry.event_type.as_str() {
"promoted" => status == "healthy" && asserted,
"promotion_rolled_back" => status == "unhealthy" && !asserted,
"health_check_error_rolled_back" => status == "error",View on GitHub (pinned to 01e15490f0)
Solutions
- Rewrite the row so all four fields are set together (or all NULL only for legacy_unverifiable / initial_activation / promotion_rejected rows).
- Audit every INSERT into harness_eval_audit to confirm it populates the four fields as one atomic group.
- Add a CHECK constraint (all four NULL or all four NOT NULL) to catch malformed writes at the DB layer.
Defensive patterns
Strategy: validation
Validate before calling
// Confirm all four fields are present together (or all absent for exempt rows).
let present = [json.is_some(), digest.is_some(), asserted.is_some(), status.is_some()];
let all_present = present.iter().all(|b| *b);
let all_absent = present.iter().all(|b| !*b);
if !all_present && !all_absent {
return Err(anyhow::anyhow!("audit row {id} has partially-populated health evidence"));
} Type guard
fn health_fields_consistent(json: Option<&str>, digest: Option<&str>, asserted: Option<bool>, status: Option<&str>) -> bool {
let p = [json.is_some(), digest.is_some(), asserted.is_some(), status.is_some()];
p.iter().all(|b| *b) || p.iter().all(|b| !*b)
} Try / catch
match verify_audit_entry(&store, &entry) {
Ok(()) => { /* ok */ }
Err(e) if e.to_string().contains("incomplete harness health evidence integrity metadata") => {
// rewrite the row so all four fields are set together (or all NULL + legacy_unverifiable)
}
Err(e) => return Err(e),
} Prevention
- Write the four health-evidence columns as a single atomic group in one INSERT.
- Add a CHECK constraint requiring all-NULL-or-all-NOT-NULL.
- Never UPDATE one of the four columns in isolation.
When it happens
Trigger: An audit row where the tuple (health_evidence_json, health_evidence_sha256, asserted_health, health_check_status) has a mix of Some and None, so the let-else (Some, Some, Some, Some) destructure fails.
Common situations: An INSERT that set json+digest but not asserted/status (or any subset); a schema migration that backfilled one column but not the others; a bug in the audit-writing code path.
Related errors
- missing harness health evidence integrity metadata
- audit health evidence does not match its evaluation
- candidate alias collision with physical candidate id
- candidate id collision with different immutable content
- harness health evidence integrity verification failed
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/4e15b41333fce421.
Report an issue: GitHub.