zeroclaw-labs/zeroclaw · error · anyhow::Error
failed step output is not captured into procedural memory
Error message
failed step output is not captured into procedural memory
What it means
capture_successful_run refuses to distill any run in which at least one step result has status SopStepStatus::Failed. Procedural memory only records fully green procedures; capturing a run with a failed step would enshrine a broken sequence (or its partial outputs) as a reusable SOP.
Source
Thrown at crates/zeroclaw-runtime/src/sop/procedural_memory.rs:104
engine: &SopEngine,
run_id: &str,
requested_by: Option<String>,
) -> Result<ProposalRecord> {
let run = engine
.get_run(run_id)
.ok_or_else(|| anyhow::Error::msg(format!("SOP run not found: {run_id}")))?;
if run.status != SopRunStatus::Completed {
bail!("only completed SOP runs can be captured");
}
if run.step_results.is_empty() {
bail!("completed run has no step results to distill");
}
if run
.step_results
.iter()
.any(|step| matches!(step.status, super::types::SopStepStatus::Failed))
{
bail!("failed step output is not captured into procedural memory");
}
let sop = engine
.get_sop(&run.sop_name)
.ok_or_else(|| anyhow::Error::msg(format!("SOP not loaded: {}", run.sop_name)))?;
let manifest_toml = read_or_default_manifest(sop)?;
let procedure_markdown = append_captured_notes(sop, run_id, &run.step_results)?;
create_proposal(
engine,
ProposalDraft {
sop_name: sop.name.clone(),
description: sop.description.clone(),
manifest_toml: Some(manifest_toml),
procedure_markdown,
source_run_id: Some(run_id.to_string()),
requested_by,
},
)View on GitHub (pinned to 88bb9c8533)
Solutions
- Re-run the SOP from scratch and only capture runs where every step succeeded.
- Fix the failing step (its inputs, tool, or environment) before capture.
- Pre-check run.step_results for any Failed status and skip capture instead of erroring.
Example fix
// before: capture a run that had a failed step patched over by approval
let p = capture_successful_run(&engine, run_id, None).await?; // bails
// after: only capture all-green runs
let run = engine.get_run(run_id).context("run missing")?;
let all_green = run.step_results.iter()
.all(|s| s.status != SopStepStatus::Failed);
if run.status == SopRunStatus::Completed && all_green {
let p = capture_successful_run(&engine, run_id, None).await?;
} Defensive patterns
Strategy: validation
Validate before calling
let Some(run) = engine.get_run(run_id) else {
anyhow::bail!("SOP run not found: {run_id}");
};
anyhow::ensure!(
run.step_results
.iter()
.all(|s| s.status != SopStepStatus::Failed),
"run contains failed steps; re-run before capture"
); Type guard
fn is_all_green(run: &SopRun) -> bool {
run.step_results
.iter()
.all(|s| s.status != SopStepStatus::Failed)
} Try / catch
match capture_successful_run(&engine, run_id, None).await {
Err(e) if e.to_string().contains("failed step output") => {
// fix the failing step and re-run the SOP end to end before capturing
}
other => other?,
} Prevention
- Only capture runs where every step succeeded.
- Do not bypass failed steps with approvals if you intend to capture the run.
- Pre-filter with get_run before calling capture.
When it happens
Trigger: Calling capture on a Completed run whose history includes a step that failed (e.g. a step failed, was retried or skipped past, and the run later completed). Any single Failed entry in run.step_results trips the guard.
Common situations: Runs where a failed step was bypassed by an operator approve/deny and execution continued; flaky steps that failed once then passed on a later manual run; attempts to capture 'mostly worked' runs.
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
- only completed SOP runs can be captured
- completed run has no step results to distill
- proposal rejected: {reason}
- proposal {} is {:?}, not pending
- proposal {} is stale; target SOP now exists
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/5767b8fb224b4a94.
Report an issue: GitHub.