zeroclaw-labs/zeroclaw · warning · anyhow::Error
cannot record checkpoint approval vote for run {run_id}: its
Error message
cannot record checkpoint approval vote for run {run_id}: its parked snapshot is not yet durably persisted (retrying) What it means
While recording a checkpoint approval vote, the broker checks engine.is_park_persist_pending(run_id). If the run's parked snapshot has not yet been durably written, the vote is refused: a vote recorded now could durably outlive a park that is lost on restart (an orphaned gate_vote row for a nonexistent run). This is a deliberate fail-closed, transient condition — it clears once the park flush completes.
Source
Thrown at crates/zeroclaw-runtime/src/sop/approval/broker.rs:400
};
if matches!(decision, ApprovalDecision::Deny { .. }) {
return Ok(None);
}
let Some((decision_label, decision_identity)) = checkpoint_decision_identity(decision)
else {
return Ok(None);
};
let checkpoint_revision = engine
.get_run(run_id)
.map(|run| run.revision)
.unwrap_or_default();
let need = policy.1.quorum.max(1) as usize;
if need <= 1 {
return Ok(None);
}
if engine.is_park_persist_pending(run_id) {
anyhow::bail!(
"cannot record checkpoint approval vote for run {run_id}: its parked snapshot is not yet durably persisted (retrying)"
);
}
engine.record_checkpoint_gate_vote(
run_id,
step,
&policy.0,
checkpoint_revision,
decision_label,
&decision_identity,
principal,
)?;
let have = self.count_qualified_voters(
engine,
run_id,
step,
&policy.0,
policy.1.required_group.as_deref().filter(|g| !g.is_empty()),View on GitHub (pinned to 88bb9c8533)
Solutions
- Retry the vote after a short delay (with bounded backoff) — the error is explicitly retryable and self-clears.
- If it persists, check engine logs for park-persist failures (disk full, DB errors) and fix the underlying IO problem.
- In automation, treat this message as a 'try again' signal, not a failure — do not re-create the run.
- Verify the runs's park state settled (run shows parked durably) before firing the second and later votes.
Example fix
// before
broker.authorize_checkpoint(run_id, step, decision).await?; // fails on first retry-window hit
// after
let mut backoff = Duration::from_millis(200);
loop {
match broker.authorize_checkpoint(run_id, step, decision.clone()).await {
Ok(out) => break out,
Err(e) if e.to_string().contains("not yet durably persisted") && backoff <= Duration::from_secs(10) => {
tokio::time::sleep(backoff).await;
backoff *= 2;
}
Err(e) => return Err(e),
}
} Defensive patterns
Strategy: retry
Validate before calling
if engine.is_park_persist_pending(run_id) {
// wait or reschedule; do not call authorize_checkpoint yet
return ScheduleRetry::after(Duration::from_millis(250));
} Try / catch
let mut delay = Duration::from_millis(200);
loop {
match broker.authorize_checkpoint(run_id, step, vote.clone()).await {
Ok(out) => break out,
Err(e) if e.to_string().contains("not yet durably persisted") && delay <= Duration::from_secs(10) => {
tokio::time::sleep(delay).await;
delay *= 2;
}
Err(e) => return Err(e),
}
} Prevention
- In approval automation, subscribe to the park-persisted event (or check is_park_persist_pending) before voting.
- Treat 'not yet durably persisted (retrying)' messages as retryable by contract, never as terminal failures.
- Keep bounded backoff (sub-second start, cap of a few seconds) — the flush normally completes quickly.
When it happens
Trigger: authorize_checkpoint (reached via resolve_via_broker) with a quorum policy needing >1 vote, invoked in the window right after the run parks but before its snapshot write reaches durable storage. More likely under slow disks, heavy IO, or immediately-scripted vote sequences.
Common situations: Automated multi-approver scripts that vote in rapid succession after a gate opens; CI pipelines approving a checkpoint within milliseconds of park; slow or saturated storage delaying the park persist; restart-adjacent races in tests.
Related errors
- cannot record approval vote for run {run_id}: its parked sna
- Run {} cannot resume: its parked checkpoint snapshot is not
- run {run_id} is parked at an approval gate; amend/revise app
- Run {} is not paused at checkpoint (status: {})
- Gateway responded {status}: {detail}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/080ed40d91712768.
Report an issue: GitHub.