affaan-m/ECC · error
valid candidate id and bounded activation evidence…
Error message
valid candidate id and bounded activation evidence reference are required
What it means
activate_initial_harness validates its inputs before touching the database: the candidate id must be exactly 64 characters (a sha256-style hex id) and the evidence reference must be non-empty (after trim) and at most 4096 characters. Any violation of these preconditions aborts the activation before a transaction is opened.
Solutions
- Pass the full 64-character v2 candidate id, not a legacy alias or display name; resolve aliases first via the alias table/resolve_harness_candidate_id.
- Trim and check the evidence_ref: it must contain at least one non-whitespace character and be at most 4096 characters.
- Truncate or shorten overly long evidence references (e.g. store the reference and pass a bounded pointer/URI instead of inline content).
- Validate inputs in your own code before calling to get a clearer error message than the generic bail.
Example fix
// before
store.activate_initial_harness("my-candidate", "")?;
// after
let id = "a1b2c3..."; // 64-char hex id
let evidence = "file://evidence/initial.json";
assert_eq!(id.len(), 64);
assert!(!evidence.trim().is_empty() && evidence.len() <= 4096);
store.activate_initial_harness(id, evidence)?; Defensive patterns
Strategy: validation
Validate before calling
fn validate_activation_args(candidate_id: &str, evidence_ref: &str) -> anyhow::Result<()> {
anyhow::ensure!(candidate_id.len() == 64, "candidate id must be a 64-char v2 id");
anyhow::ensure!(!evidence_ref.trim().is_empty(), "evidence_ref must not be empty");
anyhow::ensure!(evidence_ref.len() <= 4096, "evidence_ref must be <= 4096 chars");
Ok(())
} Type guard
fn is_v2_id(s: &str) -> bool { s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit()) } Prevention
- Resolve legacy aliases to stored v2 ids before calling activation APIs
- Keep evidence references short pointers/URIs, not inline payloads
- Mirror the library's length checks in your own input validation to fail fast
When it happens
Trigger: Calling activate_initial_harness with a candidate_id shorter or longer than 64 chars (e.g. a legacy alias id, a truncated hash, or a name), or with an evidence_ref that is empty/whitespace-only or exceeds 4096 characters.
Common situations: Passing a human-readable candidate name instead of the hex id; passing a legacy (v1) id that was not resolved through the alias table; copying an evidence URL that includes unbounded query strings; accidentally passing an empty string for evidence_ref.
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 ids, recorded-v1 evaluator, and bounded…
- 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/f366af8e35a747ad.
Report an issue: GitHub.
Appendix: source
Thrown at ecc2/src/session/store.rs:5401
self.conn.execute(
"INSERT INTO harness_candidates (id, canonical_config_json, trace_refs_json, evidence_refs_json, created_at)
VALUES (?1, ?2, ?3, ?4, ?5) ON CONFLICT(id) DO NOTHING",
rusqlite::params![candidate.id, candidate.canonical_config, trace_json, evidence_json, chrono::Utc::now().to_rfc3339()],
)?;
let stored: (String, String, String) = self.conn.query_row(
"SELECT canonical_config_json, trace_refs_json, evidence_refs_json FROM harness_candidates WHERE id = ?1",
[&candidate.id],
|row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)),
)?;
if stored != expected {
anyhow::bail!("candidate id collision with different immutable content");
}
Ok(())
}
pub fn activate_initial_harness(&self, candidate_id: &str, evidence_ref: &str) -> Result<()> {
if candidate_id.len() != 64 || evidence_ref.trim().is_empty() || evidence_ref.len() > 4096 {
anyhow::bail!(
"valid candidate id and bounded activation evidence reference are required"
);
}
let tx = self.conn.unchecked_transaction()?;
let stored_candidate_id = Self::resolve_harness_candidate_id(&tx, candidate_id)?;
if tx
.query_row(
"SELECT candidate_id FROM active_harness_config WHERE slot = 'default'",
[],
|row| row.get::<_, String>(0),
)
.optional()?
.is_some()
{
anyhow::bail!("an active harness configuration already exists");
}
let now = chrono::Utc::now().to_rfc3339();
tx.execute("INSERT INTO active_harness_config (slot, candidate_id, updated_at) VALUES ('default', ?1, ?2)", rusqlite::params![stored_candidate_id, now])?;View on GitHub (pinned to 8321021c54)