Workflow cancellation reliability improvements

Hey CircleCI community,

Canceled workflows now show reliable job status — no more status flips or phantom spinners.

We’ve shipped improvements to how CircleCI handles workflow cancellation. If you’ve canceled a workflow and noticed jobs briefly show as canceled then flip to success, or jobs that keep spinning even though they already finished, this update is for you.

What was going wrong

When a workflow was canceled, CircleCI used to mark jobs as canceled before those jobs had actually stopped on the executor. That caused two visible problems:

  • Status flipping: A job marked canceled may have already finished. When the executor reported the real result, the status could change again — so you’d see a job go from canceled → success.
  • Phantom spinners: Jobs were archived before receiving a final end timestamp. The UI treats a job with a start time but no end time as still running, so completed jobs could keep spinning indefinitely.

What we changed

CircleCI no longer marks jobs canceled until they’ve actually stopped. When you cancel a workflow:

  1. We record a “canceling” intent.
  2. We send cancel signals only to jobs that are pending or running.
  3. We wait for each job to confirm it has stopped before recording the final status.

Downstream blocked jobs are left alone and transition to skipped / not_run through the normal workflow state engine.

What you should notice

  • Canceled jobs with a terminal end time: ~51% → 99%+
  • No more canceled → success status flips
  • No more phantom spinners for jobs that have already finished

What’s next

We’re migrating the single-job cancel path to the same model. That closes the remaining gap where individually canceled jobs can still report a start time but no end time.

For the full technical write-up, see our changelog.

If you still see unexpected cancellation behavior after this change, you’re welcome to reach out to CircleCI Support with a workflow URL and timestamp — we’re happy to take a look.