Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions errors/caching-artifacts/ca-148.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
id: ca-148
title: '`actions/cache` Fails in Alpine Linux Container — BusyBox `tar` Rejects `-P` Flag'
category: caching-artifacts
severity: error
tags:
- actions-cache
- alpine
- busybox
- tar
- container
- linux
- self-hosted
patterns:
- regex: '/bin/tar: unrecognized option: P'
flags: 'i'
- regex: 'BusyBox.*tar.*unrecognized|unrecognized.*option.*P.*BusyBox'
flags: 'i'
- regex: 'Tar failed with error.*bin/tar.*exit code 1'
flags: 'i'
error_messages:
- "/bin/tar: unrecognized option: P"
- "BusyBox v1.31.1 () multi-call binary."
- "[warning]Tar failed with error: The process '/bin/tar' failed with exit code 1"
root_cause: |
`actions/cache` (v3+) invokes `tar` with the `-P` / `--absolute-names` flag when
creating or extracting cache archives that contain absolute paths. This is a GNU tar
extension that instructs tar to preserve leading slashes.

Alpine Linux ships **BusyBox tar** as `/bin/tar`, which is a minimal tar implementation
that does not support the GNU `-P` (`--absolute-names`) flag. When the cache action
calls `/bin/tar ... -P ...`, BusyBox exits immediately with:

```
/bin/tar: unrecognized option: P
BusyBox v1.31.1 () multi-call binary.
[warning]Tar failed with error: The process '/bin/tar' failed with exit code 1
```

This causes both cache save and cache restore to fail silently (the workflow continues,
but the cache is never persisted or retrieved).

The issue has been present since actions/cache introduced zstd compression with
absolute-path support and was re-reported in actions/cache#1765 (June 2026) as a
re-open of the original actions/cache#352.
fix: |
Install GNU tar in the Alpine container before the `actions/cache` step. BusyBox tar
must be replaced or overridden so that `/bin/tar` refers to the full GNU implementation.

**Option 1 — Install `tar` package in Alpine (recommended):**

```yaml
- name: Install GNU tar
run: apk add --no-cache tar
```

After `apk add tar`, Alpine's `/bin/tar` is replaced by GNU tar which supports `-P`.

**Option 2 — Use a non-Alpine base image that ships GNU tar:**

Prefer `ubuntu:24.04`, `debian:bookworm-slim`, or similar images where GNU tar is
present by default.

**Option 3 — Disable compression fallback (partial workaround):**

Some versions of `actions/cache` respect `SEGMENT_DOWNLOAD_TIMEOUT_MINS` or a `tar-*`
environment variable. Check if setting `CACHE_COMPRESSION=gzip` (if supported in your
version) avoids the `-P` flag. This is undocumented and version-dependent.
fix_code:
- language: yaml
label: "Install GNU tar before actions/cache in Alpine container"
code: |
jobs:
build:
runs-on: ubuntu-latest
container:
image: alpine:3.19
steps:
- name: Install GNU tar (required for actions/cache)
run: apk add --no-cache tar

- name: Restore cache
uses: actions/cache@v4
with:
path: ~/.cache
key: ${{ runner.os }}-cache-${{ hashFiles('**/lockfiles') }}

- name: Build
run: make build
prevention:
- "Always install GNU tar (`apk add --no-cache tar`) as an early step when using `actions/cache` in Alpine-based containers."
- "Test your full workflow in an Alpine container locally before relying on CI caching — BusyBox tar failures are silent (the workflow succeeds but the cache is never populated)."
- "Consider using `ubuntu-latest` or a Debian-based runner/container image to avoid BusyBox compatibility issues with Actions that expect GNU coreutils."
- "When using container jobs on self-hosted runners, verify the tar binary version with `tar --version` — GNU tar will print 'GNU tar' while BusyBox will not."
docs:
- url: "https://github.com/actions/cache/issues/1765"
label: "actions/cache#1765: Post cache not working on Alpine runners (2026 re-open)"
- url: "https://github.com/actions/cache/issues/352"
label: "actions/cache#352: Original Alpine / BusyBox tar compatibility issue"
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows"
label: "GitHub Docs: Caching dependencies to speed up workflows"
120 changes: 120 additions & 0 deletions errors/runner-environment/re-490.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
id: re-490
title: '`actions/setup-node` Fails When `.yarnrc.yml` Contains Yarn v4.14 `approvedGitRepositories` Key'
category: runner-environment
severity: error
tags:
- setup-node
- yarn
- yarnrc
- cache
- approvedGitRepositories
- yarn-berry
- node
- caching
patterns:
- regex: 'Unrecognized or legacy configuration settings found: approvedGitRepositories'
flags: 'i'
- regex: 'The .yarn config get cacheFolder. command failed with exit code: 1'
flags: 'i'
- regex: 'approvedGitRepositories.*run.*yarn config -v'
flags: 'i'
error_messages:
- "Usage Error: Unrecognized or legacy configuration settings found: approvedGitRepositories - run \"yarn config -v\" to see the list of settings supported in Yarn"
- "Error: The 'yarn config get cacheFolder' command failed with exit code: 1"
root_cause: |
`actions/setup-node` detects the active package manager at setup time. When `cache: 'yarn'`
is enabled (or auto-detected), it probes the Yarn cache folder by running:

```
yarn config get cacheFolder
```

Yarn v4.14 introduced `approvedGitRepositories` as a new top-level configuration key in
`.yarnrc.yml` to control which Git repositories can be used as package sources. If the
project's `.yarnrc.yml` declares `approvedGitRepositories`, but the `yarn` binary that
`setup-node` invokes is an older version that does not recognize this key, Yarn aborts
config command execution with:

```
Usage Error: Unrecognized or legacy configuration settings found: approvedGitRepositories
```

and exits with code 1. `setup-node` then fails with:

```
Error: The 'yarn config get cacheFolder' command failed with exit code: 1
```

The failure can manifest as an infinite retry loop (setup-node calls `yarn config get`
multiple times) before ultimately erroring out, wasting several minutes of job time.
fix: |
Choose the fix that best fits your situation:

**Option 1 — Pin a matching yarn version in `setup-node` (recommended):**
Add `yarn-version: '4.14.1'` (or latest) so setup-node installs a Yarn binary that
understands `approvedGitRepositories` before it probes the cache folder.

```yaml
- uses: actions/setup-node@v6
with:
node-version: '20'
cache: 'yarn'
# yarn-version is not a native setup-node input; use corepack instead:
- run: corepack enable && corepack prepare yarn@4.14.1 --activate
```

**Option 2 — Enable corepack to auto-install the correct Yarn version first:**

```yaml
- run: corepack enable
- uses: actions/setup-node@v6
with:
node-version: '20'
cache: 'yarn'
```

With corepack enabled, the `yarn` invocation during setup resolves from the
`packageManager` field in `package.json`, which should be `yarn@4.14.x`.

**Option 3 — Disable yarn cache detection in setup-node and manage cache manually:**

```yaml
- uses: actions/setup-node@v6
with:
node-version: '20'
# no cache: 'yarn' — skip the cacheFolder probe
- name: Get Yarn cache directory
id: yarn-cache-dir
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
```
fix_code:
- language: yaml
label: "Use corepack to activate the correct Yarn version before setup-node"
code: |
steps:
- uses: actions/checkout@v6

- name: Enable Corepack (installs yarn from package.json#packageManager)
run: corepack enable

- uses: actions/setup-node@v6
with:
node-version: '20'
cache: 'yarn'

- run: yarn install --immutable
prevention:
- "Always pin your Yarn version in `package.json` via the `packageManager` field (e.g., `\"packageManager\": \"yarn@4.14.1\"`) and enable corepack so all tooling uses the same binary."
- "When adding new `.yarnrc.yml` keys introduced in a specific Yarn version, ensure your CI pipeline installs that Yarn version before any step that invokes `yarn config` (including setup-node's auto-detection)."
- "Run `yarn --version` as a debug step when setup-node fails during yarn cache detection to confirm which yarn binary was being invoked."
docs:
- url: "https://github.com/actions/setup-node/issues/1534"
label: "actions/setup-node#1534: Problem with yarn v4.14 config approvedGitRepositories"
- url: "https://yarnpkg.com/configuration/yarnrc#approvedGitRepositories"
label: "Yarn Berry docs: approvedGitRepositories configuration"
- url: "https://github.com/actions/setup-node#caching-packages-dependencies"
label: "actions/setup-node: Caching package dependencies"
117 changes: 117 additions & 0 deletions errors/silent-failures/sf-228.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
id: sf-228
title: '`softprops/action-gh-release` v2.6 Converts Existing Release to Draft and Fails to Finalize New Release'
category: silent-failures
severity: error
tags:
- action-gh-release
- softprops
- release
- github-release
- tag
- overwrite
- draft
- finalize
patterns:
- regex: 'error finalizing release.*already_exists.*tag_name'
flags: 'i'
- regex: 'HttpError: Validation Failed.*Release.*already_exists.*tag_name'
flags: 'i'
- regex: 'Using release \d+ for tag .+ instead of duplicate draft \d+'
flags: 'i'
error_messages:
- "error finalizing release: HttpError: Validation Failed: {\"resource\":\"Release\",\"code\":\"already_exists\",\"field\":\"tag_name\"}"
- "retrying... (2 retries remaining)"
- "retrying... (1 retries remaining)"
root_cause: |
In `softprops/action-gh-release` v2.6.x, the release creation logic has a race condition
when creating a release for a tag that already has an existing published release and the
workflow deletes and re-creates the tag (common in nightly/rolling release patterns).

The sequence that causes the silent corruption:

1. Workflow deletes the existing tag and immediately re-creates it at the new commit.
2. The action finds TWO release objects associated with the nightly tag:
- The **old published release** (which GitHub keeps associated with the deleted tag)
- A newly-created **draft release** generated in a prior race window
3. The action logs: `Using release <id> for tag <tag> instead of duplicate draft <id>`
and selects the older published release to update.
4. While processing, the action **converts the old published release to draft** status
as part of an internal update step — without surfacing this to the user.
5. The action then attempts to create/finalize a new release and fails with:
```
error finalizing release: HttpError: Validation Failed:
{"resource":"Release","code":"already_exists","field":"tag_name"}
```
because the tag still points to the converted-to-draft old release.
6. After 3 retries the workflow fails — leaving the repository with a **draft release**
(the converted old one) and no published release for that tag.

This is a silent failure because subscriber emails fire when the old release is briefly
republished (step 4 side-effect), but then the release disappears when it reverts to
draft status — causing user confusion and empty release page state.
fix: |
**Option 1 — Pin to `v2.5.x` (immediate fix):**

Downgrade to the last stable version before v2.6 regressions:

```yaml
- uses: softprops/action-gh-release@v2.5.0
with:
tag_name: nightly
prerelease: true
files: dist/*
```

**Option 2 — Pre-delete the release before re-creating the tag:**

Use the GitHub CLI to explicitly delete the existing release before the tag
delete/recreate sequence, eliminating the duplicate-draft race:

```yaml
- name: Delete existing release
run: |
gh release delete nightly --yes --cleanup-tag || true
env:
GH_TOKEN: ${{ github.token }}

- uses: softprops/action-gh-release@v2.6.1
with:
tag_name: nightly
prerelease: true
files: dist/*
```
fix_code:
- language: yaml
label: "Stable rolling nightly release using gh CLI pre-deletion"
code: |
- name: Delete previous nightly release and tag
run: |
gh release delete nightly --yes --cleanup-tag 2>/dev/null || true
env:
GH_TOKEN: ${{ github.token }}

- name: Create new nightly release
uses: softprops/action-gh-release@v2.5.0
with:
tag_name: nightly
name: "Nightly Build ${{ github.sha }}"
prerelease: true
generate_release_notes: false
files: |
dist/Windows-*.zip
dist/Linux-*.AppImage
dist/MacOS-*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
prevention:
- "For rolling releases (nightly, latest), always delete the existing release with `gh release delete <tag> --yes --cleanup-tag` before tag re-creation to avoid the duplicate-draft race."
- "Pin action versions in workflows — use `softprops/action-gh-release@v2.5.0` or a pinned SHA until the v2.6 race condition is fixed upstream."
- "Audit release workflows after Dependabot bumps `softprops/action-gh-release` — the v2.5 → v2.6 upgrade is silent and introduces this race condition."
- "Monitor the Releases page for releases unexpectedly converting to draft status after a workflow run — this is the first symptom of this bug."
docs:
- url: "https://github.com/softprops/action-gh-release/issues/772"
label: "softprops/action-gh-release#772: Draft release gets created, and empty release gets published (v2.6.1)"
- url: "https://github.com/softprops/action-gh-release/releases"
label: "softprops/action-gh-release releases"
- url: "https://docs.github.com/en/rest/releases/releases#update-a-release"
label: "GitHub REST API: Update a release"
Loading