affaan-m/ECC · error
candidate alias collision with physical candidate id
Error message
candidate alias collision with physical candidate id
What it means
The harness candidate alias registration path refuses to create an alias whose alias_id already exists as a physical candidate id in the candidates table. It checks the physical id space first and bails 'candidate alias collision with physical candidate id' to keep the two id namespaces disjoint — an alias must never shadow a real candidate.
Solutions
- Generate alias ids in a namespace that can't collide with physical ids (prefix, e.g. 'alias:<uuid>').
- Before registering, check that alias_id is absent from the physical candidates table and pick another id on conflict.
- Deduplicate/normalize identifiers at import time so legacy aliases can't equal promoted physical ids.
- If the collision is intentional migration state, re-key the physical candidate instead of aliasing.
Example fix
// before
store.register_candidate_alias(&candidate_id, alias_id)?;
// after
let safe_alias = if store.physical_candidate_exists(alias_id) {
format!("alias:{alias_id}")
} else {
alias_id.to_string()
};
store.register_candidate_alias(&candidate_id, &safe_alias)?; Defensive patterns
Strategy: validation
Validate before calling
if store.physical_candidate_exists(alias_id) {
return Err(anyhow::anyhow!("refusing alias {alias_id}: collides with physical candidate id"));
}
store.register_candidate_alias(&candidate_id, alias_id)?; Type guard
fn is_safe_alias(id: &str) -> bool {
id.starts_with("alias:") && id.len() > 6
} Try / catch
match store.register_candidate_alias(&cid, alias) {
Err(e) if e.to_string().contains("candidate alias collision with physical candidate id") => {
retry_with_namespaced_alias()
}
other => other,
} Prevention
- Namespace aliases (e.g. 'alias:' prefix) so they can never equal physical ids.
- Check both id spaces (physical + existing aliases) before registering.
- Deduplicate identifiers during imports/migrations.
When it happens
Trigger: registering an alias (alias_id) that collides with an existing physical harness_candidate row id; auto-generated alias/id sequences overlapping after an import or rename; minting aliases from user-controlled strings that match real ids.
Common situations: Migrating candidate data where a legacy alias was later promoted to a physical candidate; tooling generating deterministic aliases that collide with real ids; two import sources producing overlapping identifiers.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- candidate alias collision with different immutable target
- candidate alias integrity verification failed
- Remote dispatch request
- Scheduled task was not found after insert
- a current bound approved draft is required
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/dc48d457f7ad7e7b.
Report an issue: GitHub.
Appendix: source
Thrown at ecc2/src/session/store.rs:5307
}
}
impl StateStore {
fn register_harness_alias(
tx: &rusqlite::Transaction<'_>,
alias_id: &str,
candidate_id: &str,
) -> Result<()> {
if tx
.query_row(
"SELECT 1 FROM harness_candidates WHERE id = ?1",
[alias_id],
|_| Ok(()),
)
.optional()?
.is_some()
{
anyhow::bail!("candidate alias collision with physical candidate id");
}
let existing = tx
.query_row(
"SELECT candidate_id FROM harness_candidate_aliases WHERE alias_id = ?1",
[alias_id],
|row| row.get::<_, String>(0),
)
.optional()?;
if let Some(existing) = existing {
if existing != candidate_id {
anyhow::bail!("candidate alias collision with different immutable target");
}
return Ok(());
}
tx.execute(
"INSERT INTO harness_candidate_aliases (alias_id, candidate_id, id_version, created_at) VALUES (?1, ?2, 2, ?3)",
rusqlite::params![alias_id, candidate_id, chrono::Utc::now().to_rfc3339()],
)?;View on GitHub (pinned to 8321021c54)