Delete GitHub Actions Caches Without Losing the Wrong Build
Run gh cache delete --all on the wrong repository and every workflow after it rebuilds from nothing. This walks the checks that catch that mistake first. You will finish with a controlled way to remove one cache, or all caches for a repository or ref, checking the target before the destructive command and making the empty-cache exit status explicit.
The route
Jump straight to the step you need, or tick off Done means at the end.
- You need: GitHub CLI installed, access to the repository, and authentication with the
reposcope. Allow about ten minutes. - What it touches: no command here needs
sudo. Cache deletion is a repository-side change, so treat it as destructive even though it does not alter source files.
1. Check the executable and its options
Start with read-only checks. The executable on this machine reports GitHub CLI 2.87.3. The installed package database separately reports gh version 2.45.0-1ubuntu0.3+esm3, so confirm gh --version whenever the executable location or package provenance matters:
$ command -v gh
/usr/bin/gh
$ gh --version
gh version 2.87.3 (2026-02-23)
$ gh cache delete --help
The local gh-cache-delete(1) manpage documents the basic cache ID, cache key, --all and --repo forms. The installed executable also offers --ref and --succeed-on-no-caches. Use the help output from the executable you will actually run as the final option reference.
Checkpoint
Do not continue until the version and repository context are clear.
2. Inspect the caches before deleting anything
List the caches for the current repository first:
$ gh cache list
ID KEY SIZE CREATED
1234 linux-build-main 42.1 MB 2026-09-20
5678 linux-build-feature 38.7 MB 2026-09-21
The rows are illustrative; your IDs, keys, sizes and dates will differ. If you are working outside the repository checkout, name the target explicitly:
$ gh cache list --repo OWNER/REPOSITORY
Replace OWNER/REPOSITORY with a real repository such as cli/cli. Do not guess from a similarly named local directory. The inherited --repo option also accepts [HOST/]OWNER/REPO for an enterprise host.
3. Delete one cache by ID
Deleting by ID is the least ambiguous choice when the list shows exactly the cache you mean. Recheck the ID immediately before running it:
$ CACHE_ID='1234'
$ gh cache list --limit 100 | grep -F -- "$CACHE_ID"
1234 linux-build-main 42.1 MB 2026-09-20
$ gh cache delete "$CACHE_ID"
✓ Deleted cache 1234
The confirmation text can vary with the CLI version. The useful verification is the command's exit status and a fresh list:
$ printf 'exit status: %s\n' "$?"
exit status: 0
$ gh cache list --limit 100 | grep -F -- "$CACHE_ID" || echo 'cache is no longer listed'
cache is no longer listed
Tip
If another process can change caches at the same time, an ID you observed a minute ago is not a permanent guarantee about the surrounding workload. Avoid automating deletion from a stale list without a policy for that race.
4. Delete by cache key, with a ref when needed
The manpage also permits a cache key instead of an ID:
$ gh cache delete 'linux-build-main'
✓ Deleted cache with key linux-build-main
A key may match more than one branch or pull request ref. On the installed 2.87.3 executable, constrain the match with the full ref syntax:
$ gh cache delete 'linux-build' --ref 'refs/heads/feature-branch'
$ gh cache delete 'linux-build' --ref 'refs/pull/42/merge'
Use the second form for a pull request merge ref, not the human-facing pull request URL. Check the key and ref with gh cache list before deleting. If your executable does not show --ref in gh cache delete --help, do not assume the option exists just because a newer guide mentions it.
5. Delete all caches only after a deliberate check
Warning
--all removes every cache in the selected repository. This cannot be undone through gh cache delete. Workflows can rebuild caches, but that costs time and may increase dependency-download traffic.
List the current target, then make the repository explicit if there is any doubt:
$ gh cache list --repo OWNER/REPOSITORY
$ gh cache delete --all --repo OWNER/REPOSITORY
✓ Deleted all caches
To remove all caches only for one branch or pull request ref, use the installed CLI's scoped form:
$ gh cache delete --all --ref 'refs/heads/feature-branch' --repo OWNER/REPOSITORY
There is no restore command. Your practical recovery is to rerun the affected workflow and let it repopulate the caches, or wait for normal workflow runs to do so. If the deletion was accidental, record the repository and ref now so the next run can be monitored.
6. Handle an empty repository cleanly
On the installed version, gh cache delete --all returns exit code 1 when no caches are found. That can make a successful cleanup look like a failed shell job. Add --succeed-on-no-caches when an empty result is an acceptable outcome:
$ gh cache delete --all --succeed-on-no-caches --repo OWNER/REPOSITORY
$ printf 'exit status: %s\n' "$?"
exit status: 0
The flag must be used with --all. It does not make a missing cache ID or an authentication failure successful. For a script, still log which repository and ref were targeted.
Common traps
- Permission errors are not a reason for more privilege. The manpage says deletion needs authorisation with the
reposcope. Check the current authentication state and repository visibility first, not with a wider shell. - Wrong repository? Repeat the command with
--repo OWNER/REPOSITORY. - Wrong ID or key? Return to
gh cache listrather than guessing. - No cache matches? Treat that as a target or timing issue, and do not fall back to
--allautomatically.
$ gh auth status
$ gh repo view OWNER/REPOSITORY --json nameWithOwner,visibility
For a script that must stop on errors, capture the status directly after deletion. Do not discard it with an unconditional true or use a broad retry that could turn a narrow deletion into a repository-wide one.
Done means
- Executable and target checked. The version and repository were confirmed.
- List inspected immediately before deletion. No stale assumptions carried over.
- Deletion was precise. A single cache by exact ID, or a key narrowed with its full ref.
- Broad deletion reviewed.
--allwas used only after an explicit review of the target and its irreversible effect. - Empty-cache case handled.
--succeed-on-no-cacheswas used where appropriate. - Recovery understood. You know recovery means rebuilding caches through later workflow runs, not restoring them with the CLI.