affaan-m/ECC · error

baseline is not the active harness configuration

Error message

baseline is not the active harness configuration

What it means

Promotion is only evaluated against the configuration that is currently active in slot 'default'. The store reads the active candidate_id and requires it to equal the stored baseline_id from the call; if the active configuration has moved on (someone else promoted, or the wrong baseline was named), the evaluation is refused so a stale baseline is never silently replaced.

Solutions

  1. Read the current active id (active_harness_config, slot 'default') immediately before the call and use it as baseline_id.
  2. Retry the evaluation with the actual current active configuration as the baseline (the compare-and-swap design assumes you re-base on current state).
  3. Serialize promotions through a single coordinator/lock if multiple processes promote concurrently.
  4. Audit harness_eval_audit for recent promotion events to understand who changed the active configuration before your call.

Example fix

// before: hardcoded stale baseline
store.evaluate_promote_and_health_check(&cand, &old_baseline, ...)?;

// after: re-base on the live active id
let current = store.active_harness_id()?.ok_or_else(|| anyhow!("no active baseline"))?;
store.evaluate_promote_and_health_check(&cand, &current, ...)?;
Defensive patterns

Strategy: retry

Validate before calling

// Re-base on the live active configuration immediately before promoting
let current_baseline = store.active_harness_id()?
    .ok_or_else(|| anyhow!("no active baseline configuration"))?;
// pass current_baseline as baseline_id, not a cached/stale id

Try / catch

match store.evaluate_promote_and_health_check(&cand, &baseline, ...) {
    Err(e) if e.to_string().contains("baseline is not the active harness configuration") => {
        let current = store.active_harness_id()?.unwrap();
        store.evaluate_promote_and_health_check(&cand, &current, ...)?
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling evaluate_promote_and_health_check with baseline_id that differs from the candidate currently recorded in active_harness_config (slot 'default'), typically after another promotion already changed the active configuration.

Common situations: Concurrent promotions where another process promoted a candidate between your snapshot and your call; passing the candidate you think is deployed rather than reading the actual active id; running a scripted promotion twice — the second run's baseline is now outdated.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/0b4fbeafb3ec8a8d. Report an issue: GitHub.

Appendix: 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 8321021c54)