Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
id: caching-artifacts-128
title: "setup-go architecture: '386' Uses Wrong Cache Key (x64 Suffix) — Cache Miss and Incorrect Isolation on Windows"
category: caching-artifacts
severity: silent-failure
tags:
- setup-go
- go
- cache
- architecture
- 386
- x86
- windows
- cache-key-bug
patterns:
- regex: 'setup-go-Windows-x64-go-.*(?:key|cache).*386|386.*setup-go.*Windows.*x64'
flags: 'i'
- regex: 'Cache not found.*setup-go-Windows-x64.*386|wrong.*architecture.*cache.*go'
flags: 'i'
error_messages:
- "Cache not found for key: setup-go-Windows-x64-go-1.22.12-{hash}"
- "setup-go-Windows-x64-go-1.22.12-{hash}"
root_cause: |
`actions/setup-go` builds its cache key using the runner OS, architecture, Go version,
and a hash of the `go.sum` file:

```
setup-go-{os}-{arch}-go-{version}-{hash}
```

When `architecture: '386'` is specified in the action's `with:` block, the intended
key is `setup-go-Windows-386-go-{version}-{hash}`. However, due to a bug in how
the architecture input is resolved for the cache key (it reads the system architecture
rather than the requested architecture), the actual key produced is:

```
setup-go-Windows-x64-go-{version}-{hash}
```

The `x64` suffix comes from the host runner architecture. A 386-targeted Go build
running on an x64 Windows runner generates a key that **collides** with a native x64
build key. This causes:

1. **Cache pollution**: if x64 and 386 builds share the same cache entry, the first
build to save wins, potentially restoring the wrong architecture's module cache.
2. **Silent cache miss**: even if the 386 cache entry was saved correctly in a prior
run, subsequent runs with `architecture: '386'` may restore the x64 cache (or vice
versa), causing unexpected build failures or incorrect binaries.

This is documented in actions/setup-go issue #749 (open as of June 2026).
fix: |
**Workaround:** Provide an explicit, architecture-disambiguated cache key using the
`cache-dependency-path` input combined with a manual `actions/cache` step that
includes the architecture in the key.

Alternatively, add a manual `key:` segment that forces architecture into the cache
key:
fix_code:
- language: yaml
label: "Workaround — manual cache step with architecture in key"
code: |
- name: Setup Go (386 architecture)
uses: actions/setup-go@v5
with:
go-version: '1.22'
architecture: '386'
cache: false # disable built-in cache to use manual key below

- name: Cache Go modules (386-specific key)
uses: actions/cache@v4
with:
path: |
~\AppData\Local\go-build
~\go\pkg\mod
# Include architecture explicitly — setup-go's built-in key omits it for 386:
key: setup-go-Windows-386-go-1.22-${{ hashFiles('**/go.sum') }}
restore-keys: |
setup-go-Windows-386-go-1.22-
- language: yaml
label: "Workaround — use separate jobs for x64 and 386 with distinct cache keys"
code: |
strategy:
matrix:
arch: ['x64', '386']
steps:
- uses: actions/setup-go@v5
with:
go-version: '1.22'
architecture: ${{ matrix.arch }}
cache: false

- uses: actions/cache@v4
with:
path: '~\AppData\Local\go-build'
key: setup-go-Windows-${{ matrix.arch }}-go-1.22-${{ hashFiles('**/go.sum') }}
prevention:
- "When using setup-go with architecture: '386' on Windows, disable the built-in cache and provide an explicit cache step that includes '386' in the key"
- "Verify cache isolation: after a 386 build, check that the saved cache key includes '386' not 'x64'"
- "Track actions/setup-go#749 for an official fix — once merged, the built-in cache will use the requested architecture in the key"
docs:
- url: "https://github.com/actions/setup-go/issues/749"
label: "actions/setup-go#749 — Cache key incorrectly uses x64 instead of 386 when architecture is set to 386"
- url: "https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-go"
label: "GitHub Docs — Building and testing Go"
- url: "https://github.com/actions/setup-go#caching-dependency-files-and-build-outputs"
label: "actions/setup-go — Caching dependency files and build outputs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
id: caching-artifacts-127
title: "upload-pages-artifact@v5 + deploy-pages@v5 Incompatible — Immutable Artifact Format Not Consumed by deploy-pages"
category: caching-artifacts
severity: error
tags:
- pages
- deploy-pages
- upload-pages-artifact
- v5
- upload-artifact-v7
- immutable-artifacts
- breaking-change
patterns:
- regex: 'deploy-pages.*failed.*artifact|artifact.*not.*found.*deploy-pages'
flags: 'i'
- regex: 'actions/deploy-pages@v5.*artifact|upload-pages-artifact@v5.*deploy-pages@v5'
flags: 'i'
- regex: 'No artifact.*github-pages|pages.*deployment.*failed.*artifact'
flags: 'i'
error_messages:
- "Error: No artifact named 'github-pages' was found for the workflow run"
- "Error: Failed to deploy to GitHub Pages: Artifact not found"
- "deploy-pages: No artifacts found for deployment"
root_cause: |
`actions/upload-pages-artifact@v5` updated its internal dependency to use
`actions/upload-artifact@v7` (the new immutable-artifacts API). This is
documented in the v5 release notes: *"Update upload-artifact action to
version 7"*.

`actions/upload-artifact@v7` creates artifacts using the new immutable
artifacts storage API (the "Results" backend). These artifacts are NOT
accessible via the old artifact API that `actions/deploy-pages@v5` uses
when downloading the `github-pages` artifact for deployment.

`actions/deploy-pages@v5` was released with only a Node.js 24 bump and
minor maintenance changes — it was **not updated** to consume artifacts from
the new immutable artifacts API. As a result, upgrading both pages actions to
v5 simultaneously leaves `deploy-pages` unable to locate the artifact uploaded
by `upload-pages-artifact`.

The symptom: the workflow succeeds through the upload step but fails at
deployment with "No artifact found" or "Artifact not found", because
`deploy-pages` is looking in the old artifact storage location.
fix: |
**Option A (recommended):** Downgrade `upload-pages-artifact` back to v4 while
keeping `deploy-pages@v5`:

```yaml
- uses: actions/upload-pages-artifact@v4 # v4 uses upload-artifact@v4 (old API)
with:
path: ./dist
- uses: actions/deploy-pages@v5
```

This pairs the old-API artifact producer with the current deployer until
`deploy-pages` is updated to support the new format.

**Option B:** Keep both at v4:

```yaml
- uses: actions/upload-pages-artifact@v4
with:
path: ./dist
- uses: actions/deploy-pages@v4
```

**Option C:** Watch `actions/deploy-pages` releases for a version that
aligns with `upload-artifact@v7` / immutable artifacts. Once released,
upgrade both to matching major versions simultaneously.
fix_code:
- language: yaml
label: "Downgrade upload-pages-artifact to v4 (pairs with deploy-pages@v5)"
code: |
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
steps:
- name: Upload pages artifact
uses: actions/upload-pages-artifact@v4 # ← pin to v4
with:
path: ./dist

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5 # v5 is fine here
- language: yaml
label: "Pin both pages actions to v4 (fully stable combination)"
code: |
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
steps:
- name: Upload pages artifact
uses: actions/upload-pages-artifact@v4
with:
path: ./dist

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
prevention:
- "When upgrading GitHub Pages actions, check the release notes of both upload-pages-artifact AND deploy-pages for API compatibility before upgrading both simultaneously"
- "Test a Pages deployment in a branch workflow before merging the version bump"
- "Pin both actions to the same major version family — v3/v4 pair or v5/v5+ once deploy-pages ships the matching update"
docs:
- url: "https://github.com/actions/upload-pages-artifact/releases"
label: "actions/upload-pages-artifact releases"
- url: "https://github.com/actions/deploy-pages/releases"
label: "actions/deploy-pages releases"
- url: "https://github.com/Azure/awesome-azd/pull/883/files"
label: "Real-world fix: revert upload-pages-artifact + deploy-pages from v5 to v4 (Azure/awesome-azd)"
- url: "https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages"
label: "GitHub Docs — Using custom workflows with GitHub Pages"
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
id: runner-environment-412
title: "Action Archive Download Returns 403 — Runner v2.335.0+ Reports AccessDeniedException Immediately (No Retry)"
category: runner-environment
severity: error
tags:
- action-download
- 403
- access-denied
- organization-policy
- private-action
- v2.335.0
- uses-step
patterns:
- regex: 'Access denied to .*(codeload\.github\.com|github\.com).*\([a-zA-Z0-9_-]+\)'
flags: 'i'
- regex: "An action could not be found at the URI '.*' \\(.*\\)"
flags: 'i'
- regex: 'action.*download.*403|403.*action.*archive'
flags: 'i'
error_messages:
- "Access denied to 'https://codeload.github.com/owner/action/tar.gz/SHA' (request-id-abc123)"
- "An action could not be found at the URI 'https://codeload.github.com/owner/action/tar.gz/SHA'"
root_cause: |
When a `uses: owner/repo@version` step runs, the runner downloads the action archive
from `codeload.github.com`. If the download returns HTTP 403 (Forbidden), the runner
throws an `AccessDeniedException` immediately.

Before runner **v2.335.0** (released June 8, 2026), a 403 response would trigger the
standard retry loop — 3 retry attempts with backoff — before eventually failing with
a generic download error. This masked the real cause and added up to 3 minutes of delay.

Starting with **runner v2.335.0** (PR #4391 — "Not retry and report action download 403"),
403 is treated as a non-retryable client-side error: the runner throws an
`AccessDeniedException` immediately and the job fails fast with a specific message
including the download URL and request ID.

Common causes of the 403:
- The action's source repository is private and the runner's GITHUB_TOKEN does not
have access to it (e.g. using a private action in a different org without proper
cross-repo access).
- The organization's Actions policy is set to an allowed-list and the action is not
on the list (`Settings → Actions → General → Actions permissions`).
- The action reference (`@SHA`, `@tag`) was deleted or made inaccessible.
- The `GITHUB_TOKEN` does not have sufficient scope to download from the target repo.
fix: |
**Check the exact blocked URL in the error message.** The `(request-id)` in the
`AccessDeniedException` message is a GitHub-side identifier for support escalation.

**If blocked by organization policy:**
Add the action to the organization's allowed-list under
`Settings → Actions → General → Actions permissions → Allow specific actions`.
Wildcard patterns like `actions/*` or `owner/*` are supported.

**If the action is private:**
Private actions must be in the same repository (or the runner must have cross-repo
access granted via GitHub Apps). Consider:
- Converting the action to a public repository.
- Using a local composite action in `.github/actions/` instead.
- Using the `secrets.GITHUB_TOKEN` of an installation token with access to the private repo.

**If using a GitHub App installation token:**
Ensure the token includes the `actions:read` or `contents:read` permission on the
action's source repository.
fix_code:
- language: yaml
label: "Allow specific action in organization policy"
code: |
# Organization Settings → Actions → General → Actions permissions
# Allowed actions (wildcard patterns):
# actions/*,octocat/example-action@v2
#
# Or in YAML for self-hosted GitHub Enterprise Server:
# github_actions:
# permissions:
# enabled: true
# allowed_actions: selected
# selected_actions:
# - owner/action@v1
- language: yaml
label: "Convert to local composite action to avoid cross-repo 403"
code: |
# Move action code to .github/actions/my-action/action.yml
# Then reference locally (no cross-repo 403 risk):
steps:
- uses: ./.github/actions/my-action
with:
input: value
prevention:
- "Pin organization Actions policies before using actions from private repos"
- "Test action access with a direct `curl` or `gh api` call to the archive URL using the same token"
- "In org policy, use the allow-list selector early — Actions blocked by policy now fail immediately (no retry delay) on runner v2.335.0+"
- "For private actions, prefer keeping them in the same repository as the workflow"
docs:
- url: "https://github.com/actions/runner/pull/4391"
label: "runner PR #4391 — Not retry and report action download 403 (shipped in v2.335.0)"
- url: "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository"
label: "GitHub Docs — Managing GitHub Actions settings (allowed actions)"
- url: "https://docs.github.com/en/actions/sharing-automations/creating-actions/about-custom-actions#using-release-management-for-actions"
label: "GitHub Docs — Using release management for actions"
Loading