{"record":{"id":"30e0689e8c80aa03","repo":"affaan-m/ECC","slug":"valid-candidate-ids-recorded-v1-evaluator-and-bo","errorCode":null,"errorMessage":"valid candidate ids, recorded-v1 evaluator, and bounded evidence reference are required","messagePattern":"valid candidate ids, recorded-v1 evaluator, and bounded evidence reference are required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ecc2/src/session/store.rs","lineNumber":5472,"sourceCode":"        candidate_id: &str,\n        baseline_id: &str,\n        evaluator: &str,\n        samples: &[PairedSample],\n        policy: PromotionPolicy,\n        evidence_ref: &str,\n        health_evidence: &HealthEvidenceSnapshot,\n        health_check: F,\n    ) -> Result<HarnessPromotionOutcome>\n    where\n        F: FnOnce(&str) -> Result<bool>,\n    {\n        if candidate_id.len() != 64\n            || baseline_id.len() != 64\n            || evaluator != \"recorded-v1\"\n            || evidence_ref.trim().is_empty()\n            || evidence_ref.len() > 4096\n        {\n            anyhow::bail!(\"valid candidate ids, recorded-v1 evaluator, and bounded evidence reference are required\");\n        }\n        health_evidence.verify()?;\n        if health_evidence.candidate_id != candidate_id || health_evidence.evaluator != evaluator {\n            anyhow::bail!(\"health evidence does not match candidate and evaluator\");\n        }\n        let comparison = policy.compare(samples)?;\n        let tx = self.conn.unchecked_transaction()?;\n        let stored_candidate_id = Self::resolve_harness_candidate_id(&tx, candidate_id)?;\n        let stored_baseline_id = Self::resolve_harness_candidate_id(&tx, baseline_id)?;\n        let active: String = tx\n            .query_row(\n                \"SELECT candidate_id FROM active_harness_config WHERE slot = 'default'\",\n                [],\n                |row| row.get(0),\n            )\n            .context(\"no active baseline configuration\")?;\n        if active != stored_baseline_id {\n            anyhow::bail!(\"baseline is not the active harness configuration\");","sourceCodeStart":5454,"sourceCodeEnd":5490,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/ecc2/src/session/store.rs#L5454-L5490","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nstore.evaluate_promote_and_health_check(&cand, &base, \"recorded\", &samples, policy, &evidence, &health, check)?;\n\n// after\nassert_eq!(cand.len(), 64);\nassert_eq!(base.len(), 64);\nassert_eq!(\"recorded-v1\", \"recorded-v1\");\nstore.evaluate_promote_and_health_check(&cand_64, &base_64, \"recorded-v1\", &samples, policy, &bounded_evidence, &health, check)?;","handlingStrategy":"validation","validationCode":"fn validate_promotion_args(candidate_id: &str, baseline_id: &str, evaluator: &str, evidence_ref: &str) -> anyhow::Result<()> {\n    anyhow::ensure!(candidate_id.len() == 64 && baseline_id.len() == 64, \"ids must be 64-char v2 ids\");\n    anyhow::ensure!(evaluator == \"recorded-v1\", \"only 'recorded-v1' evaluator is supported\");\n    anyhow::ensure!(!evidence_ref.trim().is_empty() && evidence_ref.len() <= 4096, \"evidence_ref must be non-empty and <= 4096 chars\");\n    Ok(())\n}","typeGuard":"fn is_recorded_v1(e: &str) -> bool { e == \"recorded-v1\" }","tryCatchPattern":null,"preventionTips":["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)"],"tags":["validation","input-validation","rust"],"backgroundTag":"invalid-argument-value","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}