Hmbown/CodeWhale · error
attempt finalization requires a terminal worker event
Error message
attempt finalization requires a terminal worker event
What it means
FleetLedger::finalize_task_attempt_if_ledger finalizes one exact process attempt and its receipt in a single JSONL record. The first guard (crates/tui/src/fleet/ledger.rs:965) requires the payload passed to be a terminal worker event (Completed/Failed/Cancelled); finalizing an attempt on a non-terminal payload is rejected before any lock is taken. This keeps receipt evidence pinned to an actual terminal transition.
Solutions
- Pass only Completed, Failed, or Cancelled payloads to finalize_task_attempt_if_leased.
- Append progress events via append_event_if_lease_unchanged and reserve finalize_task_attempt_if_leased for the terminal transition.
- Select the payload based on the outcome status before constructing the finalize call.
Example fix
// before
let payload = FleetWorkerEventPayload::Progress { .. };
ledger.finalize_task_attempt_if_leased(&run_id, &w, &t, attempts, &ts, payload, Some(status), receipt)?;
// after
let payload = match status {
FleetTaskLedgerStatus::Completed => FleetWorkerEventPayload::Completed { .. },
FleetTaskLedgerStatus::Failed => FleetWorkerEventPayload::Failed { .. },
_ => FleetWorkerEventPayload::Cancelled { .. },
};
ledger.finalize_task_attempt_if_leased(&run_id, &w, &t, attempts, &ts, payload, Some(status), receipt)?; Defensive patterns
Strategy: validation
Validate before calling
assert!(is_terminal_payload(&payload), "finalize requires a terminal worker event");
Try / catch
if let Err(e) = ledger.finalize_task_attempt_if_leased(...) {
if e.to_string().contains("requires a terminal worker event") { /* fix payload selection, do not retry blindly */ }
return Err(e.into());
} Prevention
- Construct finalize payloads from an exhaustive match over outcome status so only terminal variants can be produced.
- Do not share a payload variable between progress-append and finalize paths.
- Cover the finalize path with a unit test asserting non-terminal payloads are rejected.
When it happens
Trigger: Calling finalize_task_attempt_if_leased with a non-terminal FleetWorkerEventPayload (Progress, UsageReport, Heartbeat) — typically from a verifier or supervisor path that computes the receipt before selecting the terminal event variant.
Common situations: A worker wrapper that emits generic events into the finalize call; a restart-race handler that re-finalizes with a reused (non-terminal) payload; code shared between progress-append and finalize paths that forgot to branch.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- conditional terminal append requires a terminal worker event
- attempt finalization status must be terminal
- attempt receipt generation does not match its lease
- attempt receipt identity does not match its terminal event
- conditional progress append does not accept terminal worker…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/cdc44746b0b5b612.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/fleet/ledger.rs:965
#[allow(clippy::too_many_arguments)]
pub fn finalize_task_attempt_if_leased(
&self,
run_id: &FleetRunId,
worker_id: &str,
task_id: &str,
expected_attempts: u32,
timestamp: &str,
payload: FleetWorkerEventPayload,
final_status: Option<FleetTaskLedgerStatus>,
mut receipt: FleetReceipt,
) -> Result<Option<FleetWorkerEvent>> {
if !matches!(
&payload,
FleetWorkerEventPayload::Completed { .. }
| FleetWorkerEventPayload::Failed { .. }
| FleetWorkerEventPayload::Cancelled { .. }
) {
bail!("attempt finalization requires a terminal worker event");
}
if final_status.is_some_and(|status| {
!matches!(
status,
FleetTaskLedgerStatus::Completed
| FleetTaskLedgerStatus::Failed
| FleetTaskLedgerStatus::Cancelled
)
}) {
bail!("attempt finalization status must be terminal");
}
if receipt.run_id != *run_id || receipt.task_id != task_id || receipt.worker_id != worker_id
{
bail!("attempt receipt identity does not match its terminal event");
}
if receipt
.attempt
.is_some_and(|attempt| attempt != expected_attempts)View on GitHub (pinned to 73e0f67d83)