{"record":{"id":"f3fe04667f3d90e5","repo":"Hmbown/CodeWhale","slug":"conditional-progress-append-does-not-accept-terminal-worker","errorCode":null,"errorMessage":"conditional progress append does not accept terminal worker events","messagePattern":"conditional progress append does not accept terminal worker events","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/fleet/ledger.rs","lineNumber":810,"sourceCode":"    /// Append progress only while this exact worker still owns the live lease.\n    /// Host startup and stream draining use this guard so output produced after\n    /// an out-of-process cancellation cannot become durable task progress.\n    pub fn append_event_if_leased(\n        &self,\n        run_id: &FleetRunId,\n        worker_id: &str,\n        task_id: &str,\n        expected_attempts: u32,\n        timestamp: &str,\n        payload: FleetWorkerEventPayload,\n    ) -> Result<Option<FleetWorkerEvent>> {\n        if matches!(\n            &payload,\n            FleetWorkerEventPayload::Completed { .. }\n                | FleetWorkerEventPayload::Failed { .. }\n                | FleetWorkerEventPayload::Cancelled { .. }\n        ) {\n            bail!(\"conditional progress append does not accept terminal worker events\");\n        }\n        let appended = self.with_write_lock(|| {\n            let state = self.rebuild_state_unlocked()?;\n            let key = task_key(&run_id.0, task_id);\n            let Some(task) = state.tasks.get(&key) else {\n                return Ok(None);\n            };\n            if task.status != FleetTaskLedgerStatus::Leased\n                || task.leased_to.as_deref() != Some(worker_id)\n                || task.entry.attempts != expected_attempts\n            {\n                return Ok(None);\n            }\n            let event = next_worker_event(&state, run_id, worker_id, task_id, timestamp, payload);\n            self.append_record_unlocked(&FleetLedgerRecord::EventAppended {\n                event: event.clone(),\n            })?;\n            Ok(Some(event))","sourceCodeStart":792,"sourceCodeEnd":828,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/fleet/ledger.rs#L792-L828","documentation":"append_event_if_leased is the conditional progress-append path: it appends a worker event only if the calling worker still holds the live lease. Terminal outcomes (Completed, Failed, Cancelled) have their own dedicated append paths and must never flow through this guard, so passing one is rejected up front before any lock is taken.","triggerScenarios":"Calling `FleetLedger::append_event_if_leased` with a payload matching FleetWorkerEventPayload::Completed, Failed, or Cancelled.","commonSituations":"A worker draining its stream after cancellation built a final event and mistakenly passed it to the leased-guarded append instead of the terminal append API; refactored code routed all events through one helper; a host-shutdown path reused the progress append for final results.","solutions":["Route terminal payloads to the dedicated terminal append method on the ledger instead of append_event_if_leased.","Match on the payload variant before choosing the append API: terminal variants take the terminal path, everything else the conditional path.","If the event is produced during stream draining after cancellation, discard it — the lease guard exists precisely so post-cancellation output is not recorded.","Update the call site so the terminal event is only constructed after the appropriate terminal append was already performed."],"exampleFix":"// before\nledger.append_event_if_leased(&run, worker, task, attempts, ts, FleetWorkerEventPayload::Completed { .. })?;\n// after\nledger.append_terminal_event(&run, worker, task, ts, FleetWorkerEventPayload::Completed { .. })?;","handlingStrategy":"type-guard","validationCode":"// Refuse terminal payloads before calling the conditional API\nfn is_terminal(p: &FleetWorkerEventPayload) -> bool {\n    matches!(p, FleetWorkerEventPayload::Completed { .. }\n        | FleetWorkerEventPayload::Failed { .. }\n        | FleetWorkerEventPayload::Cancelled { .. })\n}\nif is_terminal(&payload) { return append_terminal(payload); }","typeGuard":"fn is_terminal(p: &FleetWorkerEventPayload) -> bool {\n    matches!(p, FleetWorkerEventPayload::Completed { .. }\n        | FleetWorkerEventPayload::Failed { .. }\n        | FleetWorkerEventPayload::Cancelled { .. })\n}","tryCatchPattern":"Err(e) if e.to_string().contains(\"does not accept terminal worker events\") =>\n    eprintln!(\"bug: route terminal payloads to the terminal append API\");","preventionTips":["Split event emitters so progress and terminal events use distinct call sites.","Add a debug assertion or unit test that no terminal variant reaches conditional appends.","Discard post-cancellation drained output instead of appending it."],"tags":["fleet","ledger","api-misuse","concurrency"],"backgroundTag":"invalid-argument-value","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}