Skip to content

Default concurrency group for workflow_dispatch causes concurrent runs to cancel each other #19467

@benvillalobos

Description

@benvillalobos

🤖 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

  1. Create a gh-aw workflow triggered by workflow_dispatch with an issue_number input
  2. Have another workflow (e.g., a label handler) dispatch it many times in quick succession
  3. 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:

  1. Include workflow_dispatch inputs in the concurrency group when they represent unique work items (e.g., issue_number)
  2. Use github.run_id as a unique key for workflow_dispatch concurrency groups so runs never collide
  3. Don't apply a default concurrency group to workflow_dispatch workflows (let users opt in)
  4. 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions