🤖 AI Assisted Bug Report
Problem
When a workflow_dispatch-triggered gh-aw workflow is invoked many times in quick succession (e.g., by a batch job applying labels), concurrent runs cancel each other because they all share the same concurrency group. Only the last pending run survives.
Runs fail with:
Canceling since a higher priority waiting request for gh-aw-{Workflow Name} exists.
Root Cause
GenerateConcurrencyConfig in concurrency.go generates a default concurrency group for workflow_dispatch workflows that has no unique identifier per run.
For workflow_dispatch, none of the special trigger checks match (isIssueWorkflow, isPullRequestWorkflow, etc.), so buildConcurrencyGroupKeys produces:
gh-aw-${{ github.workflow }}
This means ALL runs of that workflow share the same concurrency group. GitHub Actions only allows 1 running + 1 pending per group, so each new pending run replaces (cancels) the previous pending run.
There's also a second collision at the job level via GenerateJobConcurrencyConfig, which generates gh-aw-{engine-id}-${{ github.workflow }} for workflow_dispatch workflows (since hasSpecialTriggers returns false).
Reproduction
- Create a gh-aw workflow triggered by
workflow_dispatch with an issue_number input
- Have another workflow (e.g., a label handler) dispatch it many times in quick succession
- Observe that only the last pending run executes — all others are cancelled
Real-World Scenario
Our issue triage workflow is triggered via workflow_dispatch from a label handler. A separate batch job applies the stale label to many issues at once, each of which dispatches the triage workflow. The result is that only 1-2 issues actually get triaged — the rest are cancelled.
Compiled lock.yml shows:
concurrency:
group: "gh-aw-${{ github.workflow }}"
No cancel-in-progress: true is set, but GitHub Actions' default concurrency behavior still cancels pending runs when a newer pending run enters the same group (only 1 pending allowed per group).
Expected Behavior
Concurrent workflow_dispatch runs with different inputs should not cancel each other. Either:
- Include
workflow_dispatch inputs in the concurrency group when they represent unique work items (e.g., issue_number)
- Use
github.run_id as a unique key for workflow_dispatch concurrency groups so runs never collide
- Don't apply a default concurrency group to
workflow_dispatch workflows (let users opt in)
- Allow disabling the default concurrency group via frontmatter (e.g.,
concurrency: none)
Option 3 seems most aligned with the principle of least surprise — workflow_dispatch is explicitly invoked, so the caller likely intends for each invocation to run independently.
Workaround
Users can set a custom concurrency group in frontmatter that includes a unique identifier:
concurrency:
group: "my-workflow-${{ github.event.inputs.issue_number }}"
But the default behavior is surprising and the workaround is not obvious.
References
🤖 AI Assisted Bug Report
Problem
When a
workflow_dispatch-triggered gh-aw workflow is invoked many times in quick succession (e.g., by a batch job applying labels), concurrent runs cancel each other because they all share the same concurrency group. Only the last pending run survives.Runs fail with:
Root Cause
GenerateConcurrencyConfiginconcurrency.gogenerates a default concurrency group forworkflow_dispatchworkflows that has no unique identifier per run.For
workflow_dispatch, none of the special trigger checks match (isIssueWorkflow,isPullRequestWorkflow, etc.), sobuildConcurrencyGroupKeysproduces:This means ALL runs of that workflow share the same concurrency group. GitHub Actions only allows 1 running + 1 pending per group, so each new pending run replaces (cancels) the previous pending run.
There's also a second collision at the job level via
GenerateJobConcurrencyConfig, which generatesgh-aw-{engine-id}-${{ github.workflow }}forworkflow_dispatchworkflows (sincehasSpecialTriggersreturns false).Reproduction
workflow_dispatchwith anissue_numberinputReal-World Scenario
Our issue triage workflow is triggered via
workflow_dispatchfrom a label handler. A separate batch job applies thestalelabel to many issues at once, each of which dispatches the triage workflow. The result is that only 1-2 issues actually get triaged — the rest are cancelled.Compiled lock.yml shows:
No
cancel-in-progress: trueis set, but GitHub Actions' default concurrency behavior still cancels pending runs when a newer pending run enters the same group (only 1 pending allowed per group).Expected Behavior
Concurrent
workflow_dispatchruns with different inputs should not cancel each other. Either:workflow_dispatchinputs in the concurrency group when they represent unique work items (e.g.,issue_number)github.run_idas a unique key forworkflow_dispatchconcurrency groups so runs never collideworkflow_dispatchworkflows (let users opt in)concurrency: none)Option 3 seems most aligned with the principle of least surprise —
workflow_dispatchis explicitly invoked, so the caller likely intends for each invocation to run independently.Workaround
Users can set a custom concurrency group in frontmatter that includes a unique identifier:
But the default behavior is surprising and the workaround is not obvious.
References
pkg/workflow/concurrency.go