How to Force Stop a GitHub Actions Workflow

Introduction

Sometimes a GitHub Actions workflow keeps running forever. For example, a deployment job does not exit, the runner crashes, a Docker child process does not stop, or a self-hosted runner becomes unresponsive. In these cases, the normal cancel action may not work, so you need a force stop method.

Solution

Option 1: Cancel it from the GitHub web UI

This is the simplest way.

  1. Open the repository Actions page
  2. Open the running workflow
  3. Click Cancel workflow or Cancel jobs
  4. If normal cancellation does not work, click Force cancel workflow

Force cancel workflow is useful when the workflow is stuck and cannot exit normally.

Option 2: Cancel it with GitHub CLI

If you already have GitHub CLI installed, using the command line is usually faster.

First, list the current workflow runs:

gh run list

The output is usually similar to this:

STATUS    TITLE        WORKFLOW   BRANCH
running   deploy       CI         main

Normal cancel:

gh run cancel <run-id>

For example:

gh run cancel 26392735720

If that does not work, use force cancel:

gh run cancel 26392735720 --force

Option 3: Force cancel it with the API

GitHub Actions provides a REST API to force cancel a workflow run.

The endpoint format is:

POST /repos/{owner}/{repo}/actions/runs/{run_id}/force-cancel

For example, if the page URL is:

https://github.com/openHacking/PyDeskUI/actions/runs/26392735720/job/77686565248

Then:

  • OWNER is openHacking
  • REPO is PyDeskUI
  • RUN_ID is 26392735720
  • The trailing 77686565248 is the job id, not the run id

So the API URL is:

https://api.github.com/repos/openHacking/PyDeskUI/actions/runs/26392735720/force-cancel

Full example:

curl -L \
  -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer <TOKEN>" \
  https://api.github.com/repos/openHacking/PyDeskUI/actions/runs/26392735720/force-cancel

If GitHub CLI is already authenticated on your machine, this command is usually easier:

gh run cancel 26392735720 --force

Option 4: Kill a stuck self-hosted runner

If the repository uses a self-hosted runner, sometimes the real problem is not the workflow itself but the runner process. In that case, even Force cancel workflow may not stop it.

You can go to the runner machine and kill the related process directly.

First, find the process:

ps aux | grep Runner

Or:

ps aux | grep actions

Then force kill it:

kill -9 <pid>

If your runner is inside Docker, you can kill the container instead:

docker ps
docker kill <container-id>

Extra Tip

If the same workflow often gets queued repeatedly and old runs block the runner, you can add concurrency control to the workflow so that newer runs automatically cancel older ones:

concurrency:
  group: deploy-${{ github.ref }}
  cancel-in-progress: true

This reduces the chance of old deployment jobs piling up and needing manual cleanup.

Reference

Comments