Dequeued tasks can now be cancelled from the runs list
The web application now allows operators to cancel dequeued tasks directly from the main runs list, eliminating the need to click into individual task pages to halt pending operations.
Users managing task pipelines can now cancel runs that are in the "dequeued" state directly from the main runs list. Previously, tasks that had been claimed by a worker but hadn't quite started executing were missing the cancel button on the list view, forcing users to click through to the individual run's details page just to stop them.
This small but impactful fix in the web application's task management UI removes unnecessary friction. By aligning the list view's logic with the single-run page, operators can monitor and immediately halt stalled or misfiring tasks without breaking their workflow.
View Original GitHub DescriptionFact Check
The cancel button was missing from the runs list for runs in DEQUEUED status. The runs list gates the button on run.isCancellable, which goes through isCancellableRunStatus -> CANCELLABLE_RUN_STATUSES = NON_FINAL_RUN_STATUSES. DEQUEUED was never added to that list when it was introduced in the run engine.
The single run page uses a separate check (!run.isFinished, i.e. the inverse of FINAL_RUN_STATUSES), so cancellation already worked there - only the list was affected.
Adding DEQUEUED to NON_FINAL_RUN_STATUSES also flips isCrashableRunStatus and isFailableRunStatus, but:
- The crash path is the right behaviour - a
DEQUEUEDrun (worker has claimed but not yet executing) can legitimately crash beforeEXECUTING, same asPENDING/DELAYEDalready do. - The fail path (
failedTaskRun.server.ts) is only reached from V1 code paths (marqs consumers, v1 heartbeat handler).DEQUEUEDis a V2-engine-only status, so V1 consumers never see it.
When cancelling a DEQUEUED run the execution snapshot goes to PENDING_CANCEL (worker must ack) but TaskRun.status flips to CANCELED immediately - the UI reflects cancellation without waiting for the worker. Added an integration test in run-engine/src/engine/tests/cancelling.test.ts covering the full trigger -> dequeue -> cancel -> worker-ack flow.
Stall safety
The stall recovery path (PENDING_EXECUTING heartbeat miss -> nack-and-requeue -> back to QUEUED) lives entirely inside @internal/run-engine and never touches the webapp's taskStatus.ts helpers - the engine has zero imports from ~/v3/taskStatus and doesn't know CrashTaskRunService / FailedTaskRunService exist. A stalled DEQUEUED run still goes back to the queue for retry; this change cannot cause stalls to crash or fail.
The only realistic impact is the intended UI fix - the theoretical V1 crash/fail branches for DEQUEUED are unreachable in practice because V1 runs never have DEQUEUED status.