affaan-m/ECC · error

valid candidate ids, recorded-v1 evaluator, and bounded…

Error message

valid candidate ids, recorded-v1 evaluator, and bounded evidence reference are required

What it means

evaluate_promote_and_health_check validates its arguments up front: both candidate_id and baseline_id must be exactly 64 characters, evaluator must be the literal "recorded-v1", and evidence_ref must be non-blank and at most 4096 characters. Any violation aborts before policy comparison or any database work.

Solutions

  1. Use evaluator == "recorded-v1" exactly; there is no other supported evaluator in this API version.
  2. Resolve both ids to their 64-character stored v2 ids before calling (resolve via the alias table), and length-check them.
  3. Trim and bound the evidence_ref (non-empty, <= 4096 chars); store large payloads externally and pass a short reference.
  4. Add client-side validation mirroring these rules so you fail fast with a clearer message.

Example fix

// before
store.evaluate_promote_and_health_check(&cand, &base, "recorded", &samples, policy, &evidence, &health, check)?;

// after
assert_eq!(cand.len(), 64);
assert_eq!(base.len(), 64);
assert_eq!("recorded-v1", "recorded-v1");
store.evaluate_promote_and_health_check(&cand_64, &base_64, "recorded-v1", &samples, policy, &bounded_evidence, &health, check)?;
Defensive patterns

Strategy: validation

Validate before calling

fn validate_promotion_args(candidate_id: &str, baseline_id: &str, evaluator: &str, evidence_ref: &str) -> anyhow::Result<()> {
    anyhow::ensure!(candidate_id.len() == 64 && baseline_id.len() == 64, "ids must be 64-char v2 ids");
    anyhow::ensure!(evaluator == "recorded-v1", "only 'recorded-v1' evaluator is supported");
    anyhow::ensure!(!evidence_ref.trim().is_empty() && evidence_ref.len() <= 4096, "evidence_ref must be non-empty and <= 4096 chars");
    Ok(())
}

Type guard

fn is_recorded_v1(e: &str) -> bool { e == "recorded-v1" }

Prevention

When it happens

Trigger: Calling evaluate_promote_and_health_check with an id that is not exactly 64 chars (alias, name, truncated hash), with an evaluator string other than "recorded-v1" (e.g. "recorded", "v1", or a custom name), or with an empty/over-length evidence_ref.

Common situations: Introducing a new evaluator label that the API does not support yet; passing display names instead of hex ids; evidence references built from unbounded user input or long inline payloads.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at ecc2/src/session/store.rs:5472

        candidate_id: &str,
        baseline_id: &str,
        evaluator: &str,
        samples: &[PairedSample],
        policy: PromotionPolicy,
        evidence_ref: &str,
        health_evidence: &HealthEvidenceSnapshot,
        health_check: F,
    ) -> Result<HarnessPromotionOutcome>
    where
        F: FnOnce(&str) -> Result<bool>,
    {
        if candidate_id.len() != 64
            || baseline_id.len() != 64
            || evaluator != "recorded-v1"
            || evidence_ref.trim().is_empty()
            || evidence_ref.len() > 4096
        {
            anyhow::bail!("valid candidate ids, recorded-v1 evaluator, and bounded evidence reference are required");
        }
        health_evidence.verify()?;
        if health_evidence.candidate_id != candidate_id || health_evidence.evaluator != evaluator {
            anyhow::bail!("health evidence does not match candidate and evaluator");
        }
        let comparison = policy.compare(samples)?;
        let tx = self.conn.unchecked_transaction()?;
        let stored_candidate_id = Self::resolve_harness_candidate_id(&tx, candidate_id)?;
        let stored_baseline_id = Self::resolve_harness_candidate_id(&tx, baseline_id)?;
        let active: String = tx
            .query_row(
                "SELECT candidate_id FROM active_harness_config WHERE slot = 'default'",
                [],
                |row| row.get(0),
            )
            .context("no active baseline configuration")?;
        if active != stored_baseline_id {
            anyhow::bail!("baseline is not the active harness configuration");

View on GitHub (pinned to 8321021c54)