{"record":{"id":"f366af8e35a747ad","repo":"affaan-m/ECC","slug":"valid-candidate-id-and-bounded-activation-evidence","errorCode":null,"errorMessage":"valid candidate id and bounded activation evidence reference are required","messagePattern":"valid candidate id and bounded activation evidence reference are required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ecc2/src/session/store.rs","lineNumber":5401,"sourceCode":"        self.conn.execute(\n            \"INSERT INTO harness_candidates (id, canonical_config_json, trace_refs_json, evidence_refs_json, created_at)\n             VALUES (?1, ?2, ?3, ?4, ?5) ON CONFLICT(id) DO NOTHING\",\n            rusqlite::params![candidate.id, candidate.canonical_config, trace_json, evidence_json, chrono::Utc::now().to_rfc3339()],\n        )?;\n        let stored: (String, String, String) = self.conn.query_row(\n            \"SELECT canonical_config_json, trace_refs_json, evidence_refs_json FROM harness_candidates WHERE id = ?1\",\n            [&candidate.id],\n            |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)),\n        )?;\n        if stored != expected {\n            anyhow::bail!(\"candidate id collision with different immutable content\");\n        }\n        Ok(())\n    }\n\n    pub fn activate_initial_harness(&self, candidate_id: &str, evidence_ref: &str) -> Result<()> {\n        if candidate_id.len() != 64 || evidence_ref.trim().is_empty() || evidence_ref.len() > 4096 {\n            anyhow::bail!(\n                \"valid candidate id and bounded activation evidence reference are required\"\n            );\n        }\n        let tx = self.conn.unchecked_transaction()?;\n        let stored_candidate_id = Self::resolve_harness_candidate_id(&tx, candidate_id)?;\n        if tx\n            .query_row(\n                \"SELECT candidate_id FROM active_harness_config WHERE slot = 'default'\",\n                [],\n                |row| row.get::<_, String>(0),\n            )\n            .optional()?\n            .is_some()\n        {\n            anyhow::bail!(\"an active harness configuration already exists\");\n        }\n        let now = chrono::Utc::now().to_rfc3339();\n        tx.execute(\"INSERT INTO active_harness_config (slot, candidate_id, updated_at) VALUES ('default', ?1, ?2)\", rusqlite::params![stored_candidate_id, now])?;","sourceCodeStart":5383,"sourceCodeEnd":5419,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/ecc2/src/session/store.rs#L5383-L5419","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nstore.activate_initial_harness(\"my-candidate\", \"\")?;\n\n// after\nlet id = \"a1b2c3...\"; // 64-char hex id\nlet evidence = \"file://evidence/initial.json\";\nassert_eq!(id.len(), 64);\nassert!(!evidence.trim().is_empty() && evidence.len() <= 4096);\nstore.activate_initial_harness(id, evidence)?;","handlingStrategy":"validation","validationCode":"fn validate_activation_args(candidate_id: &str, evidence_ref: &str) -> anyhow::Result<()> {\n    anyhow::ensure!(candidate_id.len() == 64, \"candidate id must be a 64-char v2 id\");\n    anyhow::ensure!(!evidence_ref.trim().is_empty(), \"evidence_ref must not be empty\");\n    anyhow::ensure!(evidence_ref.len() <= 4096, \"evidence_ref must be <= 4096 chars\");\n    Ok(())\n}","typeGuard":"fn is_v2_id(s: &str) -> bool { s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit()) }","tryCatchPattern":null,"preventionTips":["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"],"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"}