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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions