affaan-m/ECC · error · anyhow::Error

baseline is not the active harness configuration

Error message

baseline is not the active harness configuration

What it means

promote_harness requires that the baseline_id argument equals the currently active candidate in slot 'default'. Promotion is always relative to the live baseline: you cannot promote against a stale or hypothetical baseline.

Source

Thrown at ecc2/src/session/store.rs:5490

            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");
        }
        let now = chrono::Utc::now().to_rfc3339();
        if !comparison.passed {
            tx.execute("INSERT INTO harness_evaluations (candidate_id, baseline_id, evaluator, samples_json, policy_json, comparison_json, evidence_ref, legacy_unverifiable, created_at) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, 0, ?8)", rusqlite::params![stored_candidate_id, stored_baseline_id, evaluator, serde_json::to_string(samples)?, serde_json::to_string(&policy)?, serde_json::to_string(&comparison)?, evidence_ref, now])?;
            let evaluation_id = tx.last_insert_rowid();
            tx.execute("INSERT INTO harness_eval_audit (event_type, candidate_id, prior_candidate_id, evaluation_id, evidence_ref, legacy_unverifiable, created_at) VALUES ('promotion_rejected', ?1, ?2, ?3, ?4, 0, ?5)", rusqlite::params![stored_candidate_id, stored_baseline_id, evaluation_id, evidence_ref, now])?;
            tx.commit()?;
            return Ok(HarnessPromotionOutcome {
                evaluation_id: Some(evaluation_id),
                promoted: false,
                rolled_back: false,
                failures: comparison.failures,
            });
        }
        let changed = tx.execute("UPDATE active_harness_config SET candidate_id = ?1, updated_at = ?2 WHERE slot = 'default' AND candidate_id = ?3", rusqlite::params![stored_candidate_id, now, stored_baseline_id])?;
        if changed != 1 {
            anyhow::bail!("atomic promotion compare-and-swap failed");
        }

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Re-read the active candidate id immediately before promoting and pass it as baseline_id.
  2. Serialize all promotions behind a single-writer / mutex so the baseline cannot change mid-call.
  3. Use resolve_harness_candidate_id to canonicalize both ids before comparing, so aliases do not cause false mismatches.

Example fix

// before
store.promote_harness(&candidate_id, &stale_baseline_id, ...)?;

// after
let live_baseline = store.active_harness_id()?.ok_or_else(|| anyhow::anyhow!("no active harness"))?;
store.promote_harness(&candidate_id, &live_baseline, ...)?;
Defensive patterns

Strategy: validation

Validate before calling

let live_baseline = store.active_harness_id()? // or the store's active getter
    .ok_or_else(|| anyhow::anyhow!("no active harness to promote against"))?;
if live_baseline != baseline_id {
    // re-read happened; adopt the live baseline or abort
    return Err(anyhow::anyhow!("baseline {baseline_id} is stale; live active is {live_baseline}"));
}
store.promote_harness(&candidate_id, &live_baseline, ...)?;

Type guard

fn baseline_is_active(active: &str, baseline_id: &str) -> bool {
    active == baseline_id
}

Try / catch

match store.promote_harness(&candidate_id, &baseline_id, ...) {
    Ok(out) => { /* handled */ }
    Err(e) if e.to_string().contains("baseline is not the active") => {
        // re-read active config and retry with the fresh baseline
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: baseline_id (after resolve_harness_candidate_id) != the active_harness_config 'default' candidate_id. The active row is read with .context("no active baseline configuration") just before the comparison.

Common situations: Stale baseline captured before a prior promotion completed; a concurrent promotion already changed the active config; passing candidate_id as baseline_id by argument-order mistake.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/0b4fbeafb3ec8a8d. Report an issue: GitHub.