affaan-m/ECC · error

health evidence does not match promoted candidate

Error message

health evidence does not match promoted candidate

What it means

health_check verifies that the recorded health evidence belongs to the candidate actually being promoted. This error is thrown when evaluate_promote_and_health_check is called for a candidate id that differs from the single candidate id recorded in the evidence's health map. The recorded evaluator refuses to treat health evidence for a different candidate as proof for this promotion.

Solutions

  1. Promote the same candidate id that owns the single health entry in the recorded evidence.
  2. Re-record or regenerate the evidence with health keyed to the candidate you intend to promote.
  3. Compare ids for exact string equality, including case and trailing whitespace, before calling evaluate_promote_and_health_check.
  4. If comparing multiple candidates, use separate RecordedEvaluator instances, one per candidate's evidence.

Example fix

// before
let eval = RecordedEvaluator::from_evidence(evidence_for_candidate_a)?;
let result = eval.evaluate_promote_and_health_check("candidate-b", ...)?; // mismatch bails

// after
let eval = RecordedEvaluator::from_evidence(evidence_for_candidate_a)?;
let result = eval.evaluate_promote_and_health_check("candidate-a", ...)?; // matches health key
Defensive patterns

Strategy: type-guard

Validate before calling

let (health_candidate, _) = evidence.health.iter().next().unwrap();
assert_eq!(health_candidate, candidate_to_promote);

Type guard

fn health_matches(evidence: &RecordedEvidence, candidate_id: &str) -> bool {
    evidence.health.len() == 1 && evidence.health.contains_key(candidate_id)
}

Prevention

When it happens

Trigger: Calling evaluate_promote_and_health_check with a candidate_id string that does not exactly match the key stored in the RecordedEvidence health map (e.g. promoting "candidate-b" while health evidence was recorded for "candidate-a").

Common situations: Mixing up candidate ids when multiple candidates share an evidence file; ids differing by whitespace/case/encoding; replaying evidence recorded in a previous run against a newly generated candidate id.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/157838a9b22a4a04. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/harness_eval.rs:447

    fn evaluate(&mut self, candidate_id: &str, seed: u64) -> Result<f64> {
        self.calls.push((candidate_id.to_string(), seed));
        let score = *self
            .scores
            .get(&(candidate_id.to_string(), seed))
            .with_context(|| format!("missing recorded score for {candidate_id} seed {seed}"))?;
        if !score.is_finite() || !(0.0..=1.0).contains(&score) {
            bail!("score must be finite and between 0 and 1");
        }
        Ok(score)
    }

    fn health_check(&mut self, candidate_id: &str) -> Result<bool> {
        if self
            .health_candidate
            .as_deref()
            .is_some_and(|expected| expected != candidate_id)
        {
            bail!("health evidence does not match promoted candidate");
        }
        Ok(self.health_ok)
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PairedSample {
    pub seed: u64,
    pub candidate_score: f64,
    pub baseline_score: f64,
}

pub fn evaluate_paired(
    evaluator: &mut dyn Evaluator,
    candidate_id: &str,
    baseline_id: &str,
    seeds: &[u64],
) -> Result<Vec<PairedSample>> {

View on GitHub (pinned to 8321021c54)