zeroclaw-labs/zeroclaw · error · anyhow::Error

Active run not found

Error message

Active run not found: {}

What it means

The resume path could not find the run id in the engine's active_runs map, so there is nothing to resume. The engine logs a WARN Reject event with the run_id before bailing. Active runs are the in-memory execution surface (the durable store is the concurrency source of truth), so the id is unknown, expired, or was lost when the engine restarted.

Solutions

  1. List or query current runs to find the live run id before resuming.
  2. After an engine restart, re-admit/resume parked runs through the store-backed recovery path rather than replaying stale ids.
  3. Take the run id from the checkpoint notification itself, not from a stored or hand-typed copy.

Example fix

// before: resume with an id captured before an engine restart
engine.resume_checkpoint(state).await?; // state.run_id no longer active

// after: re-resolve the live run id first
let run_id = engine
    .list_runs()
    .into_iter()
    .find(|r| r.sop_name == state.sop_name && r.status == SopRunStatus::PausedCheckpoint)
    .map(|r| r.run_id)
    .ok_or_else(|| anyhow::anyhow!("no parked run for SOP {}", state.sop_name))?;
engine.resume_checkpoint(state.with_run_id(run_id)).await?;
Defensive patterns

Strategy: validation

Validate before calling

let Some(run) = engine.get_run(&state.run_id) else {
    // stale id (e.g. after engine restart): re-resolve the parked run from the live list
    anyhow::bail!("active run {} not found; re-resolve from list_runs", state.run_id);
};
engine.resume_checkpoint(state).await?;

Try / catch

match engine.resume_checkpoint(state).await {
    Err(e) if e.to_string().contains("Active run not found") => {
        // refresh the run id from the engine's live runs and retry once
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling resume with a run id that was never active in this process, was evicted after completion, or belonged to a previous engine instance before a restart; truncated or mistyped run ids from configuration or messages.

Common situations: Engine restart between checkpoint pause and resume; long-lived cron or channel handlers holding stale run ids; copy-pasting an id from old logs.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/41c81c1e9ed55137. Report an issue: GitHub.

Appendix: source

Thrown at crates/zeroclaw-runtime/src/sop/engine.rs:4323

        let sop_name = match self.active_runs.get(&state.run_id) {
            Some(run) if run.status == SopRunStatus::PausedCheckpoint => run.sop_name.clone(),
            Some(run) => {
                bail!(
                    "Run {} is not paused at checkpoint (status: {})",
                    state.run_id,
                    run.status
                );
            }
            None => {
                let run_id = state.run_id.clone();
                ::zeroclaw_log::record!(
                    WARN,
                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)
                        .with_outcome(::zeroclaw_log::EventOutcome::Failure)
                        .with_attrs(::serde_json::json!({"run_id": run_id})),
                    "SOP engine: active run not found"
                );
                bail!("Active run not found: {}", state.run_id);
            }
        };

        // Refuse to resume while the checkpoint's parked snapshot has not yet
        // been durably persisted (see `is_park_persist_pending`'s doc): the kept
        // claim predates this attempt, and reacquiring on top of it would give a
        // later rollback or a maintenance retry no way to distinguish "freshly
        // reacquired" from "pre-existing, must survive."
        if self.is_park_persist_pending(&state.run_id) {
            bail!(
                "Run {} cannot resume: its parked checkpoint snapshot is not yet durably persisted (retrying)",
                state.run_id
            );
        }

        let sop = self
            .sops
            .iter()

View on GitHub (pinned to 88bb9c8533)