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
- Use evaluator == "recorded-v1" exactly; there is no other supported evaluator in this API version.
- Resolve both ids to their 64-character stored v2 ids before calling (resolve via the alias table), and length-check them.
- Trim and bound the evidence_ref (non-empty, <= 4096 chars); store large payloads externally and pass a short reference.
- 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
- Hardcode the evaluator constant "recorded-v1" rather than building it dynamically
- Resolve ids through the alias table to their 64-char stored form before calls
- Bound evidence references at creation time (truncate or store externally)
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
- valid candidate id and bounded activation evidence…
- candidate configuration exceeds 1 MiB
- exactly one candidate-keyed health assertion is required
- harness health evidence exceeds integrity verification bound
- harness health evidence is inconsistent with audit outcome
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)