When result.get("status") returns "cancelled", mark_cancelled is called and attempt.status becomes CANCELLED. Then update_attempt persists it. After the persistence block, the code checks attempt.status and falls through to attempt.failed only when the status is NOT COMPLETED and NOT CANCELLED. That path works correctly. However, if mark_cancelled succeeds but a subsequent step (e.g., self.store.update_attempt(attempt)) raises, the except clause at line 230-233 calls attempt.mark_failed(error=...) which overwrites the status to FAILED. This is handled and signals a failure. The more subtle issue is that within the try block after mark_cancelled, attempt.run_dir = result.get("run_dir") (line 219) and attempt.metrics = result.get("metrics") (line 220) are assigned before self.store.update_attempt(attempt) and the terminal event emission. If either of those assignments triggers an attribute assignment error (unlikely for a dataclass but theoretically possible due to descriptor issues or type mismatch), the except handler will catch it and call mark_failed, which again chains. While this is defensive, the more concrete concern is that attempt.run_dir and attempt.metrics are populated unconditionally after the status branch. For a "cancelled" status, we end up writing error in mark_cancelled, then we possibly write run_dir and metrics to the attempt (which may be stale or None from the result), and then persist and emit. This ordering means the cancelled attempt carries a run_dir from the agent, which might be a path that is later cleaned up or shared with another attempt, but the cancelled attempt is not expected to have a run_dir in the default case. This is a minor data correctness issue.