GitHub Actions concurrency group not canceling old runs: how to debug
Debugs concurrency groups that fail to cancel superseded runs. Use when old runs keep going despite cancel-in-progress, when concurrency groups do not seem to group, or when deploys race. Not for job-level parallelism.
TL;DR
Concurrency groups fail to cancel for two reasons: the group expression evaluates differently per run (so the runs are not actually in the same group), or cancel-in-progress is not set (the default is to queue, not cancel). Check the evaluated group name in the run logs first; identical runs must show identical group names.
The query
GitHub Actions concurrency group not canceling old runs: how to debugUse this when
- Old runs continue after new pushes
- Deploys race between concurrent runs
- Concurrency seems configured but ineffective
- After changing group expressions
Not for when
- Parallel jobs within one run (different mechanism)
- Runner capacity queuing
- Step-level timeouts
Steps
Step 1: Verify the group names match across runs
Check the evaluated concurrency group in each run's logs. If run A is in group "deploy-main" and run B is in "deploy-main-2", they are different groups and will never cancel each other. The expression must be deterministic per branch. Expected output: group names compared; mismatch found or ruled out.
Step 2: Confirm cancel-in-progress is set
The default concurrency behavior queues; cancellation requires cancel-in-progress: true explicitly. A group without it serializes runs instead of canceling, which looks like "not canceling" but is working as configured. Expected output: the setting confirmed present, or added.
Step 3: Check where the concurrency is defined
Concurrency at the workflow top level groups whole runs; at the job level it groups jobs. A job-level group does not cancel other jobs' runs. For deploy cancellation you almost always want the top-level group. Expected output: the concurrency scope matching the intent (whole run vs job).
Step 4: Watch for expression pitfalls
Dynamic group names using github.sha change every run (never grouping); using run_id is similarly useless for cancellation. Group by branch or PR number: the stable identity of the thing you want serialized. Expected output: the group expression using a stable identifier.
Step 5: Test with two rapid pushes
Push twice in quick succession and watch: the first run should cancel when the second starts. This is the definitive test; configuration review alone misses evaluation subtleties. Expected output: cancellation observed working end to end.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst7qzzNQQ68Cnsyy8OMTNYg
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.