@htekdev/actions-debugger 1.0.129 → 1.0.131
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/errors/permissions-auth/permissions-auth-076.yml +158 -0
- package/errors/runner-environment/runner-environment-241.yml +154 -0
- package/errors/runner-environment/runner-environment-242.yml +131 -0
- package/errors/runner-environment/runner-environment-243.yml +120 -0
- package/errors/runner-environment/runner-environment-244.yml +136 -0
- package/errors/runner-environment/runner-environment-245.yml +160 -0
- package/errors/silent-failures/silent-failures-120.yml +132 -0
- package/errors/yaml-syntax/yaml-syntax-077.yml +141 -0
- package/package.json +1 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
id: permissions-auth-076
|
|
2
|
+
title: '`docker push` to ghcr.io fails with 403 / "denied: permission_denied: write_package" — missing `packages: write` permission'
|
|
3
|
+
category: permissions-auth
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- ghcr
|
|
7
|
+
- github-packages
|
|
8
|
+
- container-registry
|
|
9
|
+
- packages-write
|
|
10
|
+
- github-token
|
|
11
|
+
- docker-push
|
|
12
|
+
- 403
|
|
13
|
+
- permission-denied
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'denied: permission_denied: write_package'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'Error response from daemon.*denied.*ghcr\.io.*403'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
- regex: 'error parsing HTTP 403 response body.*ghcr\.io'
|
|
20
|
+
flags: 'i'
|
|
21
|
+
- regex: 'unauthorized.*ghcr\.io.*write'
|
|
22
|
+
flags: 'i'
|
|
23
|
+
- regex: 'The token provided does not match expected format for.*packages'
|
|
24
|
+
flags: 'i'
|
|
25
|
+
error_messages:
|
|
26
|
+
- "Error response from daemon: denied: permission_denied: write_package"
|
|
27
|
+
- "error parsing HTTP 403 response body: unexpected end of JSON input: \"\""
|
|
28
|
+
- "denied: denied"
|
|
29
|
+
- "unauthorized: authentication required"
|
|
30
|
+
- "buildx failed with: ERROR [auth] ghcr.io token refreshing failed with status: 403 Forbidden"
|
|
31
|
+
root_cause: |
|
|
32
|
+
GitHub Container Registry (ghcr.io) requires the `packages: write` permission
|
|
33
|
+
to be explicitly granted in the workflow job's `permissions:` block before
|
|
34
|
+
`GITHUB_TOKEN` can push (publish) images.
|
|
35
|
+
|
|
36
|
+
Since GitHub tightened default GITHUB_TOKEN permissions in 2023, new repositories
|
|
37
|
+
and organization workflows that set "Restrict GitHub Actions permissions" to
|
|
38
|
+
"Read repository contents and packages" have `packages: write` DISABLED by default.
|
|
39
|
+
Without this permission, any `docker push` or `docker buildx build --push` to
|
|
40
|
+
`ghcr.io` fails with a 403 at the registry level.
|
|
41
|
+
|
|
42
|
+
**Why this is confusing:**
|
|
43
|
+
- `docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}`
|
|
44
|
+
SUCCEEDS (read/login is allowed) — the login step passes
|
|
45
|
+
- The failure occurs on `docker push`, not login
|
|
46
|
+
- The error message "denied: permission_denied: write_package" or the generic 403
|
|
47
|
+
does not directly mention the `packages: write` permission or how to add it
|
|
48
|
+
- The same workflow may work on repositories created before the permission
|
|
49
|
+
tightening (where `packages: write` was still the default)
|
|
50
|
+
|
|
51
|
+
**Additional requirement — linking the package to the repository:**
|
|
52
|
+
On first publish, the package is created as unlinked. If the workflow runs in a
|
|
53
|
+
fork or if the package visibility is set to Private with no repository link, the
|
|
54
|
+
GITHUB_TOKEN push will also fail even with `packages: write`. The package must be
|
|
55
|
+
linked to the source repository for GITHUB_TOKEN to authenticate.
|
|
56
|
+
|
|
57
|
+
Source: SO #70646920 (22 upvotes, 34k views), SO #78342148, GitHub Docs on
|
|
58
|
+
container registry permissions.
|
|
59
|
+
fix: |
|
|
60
|
+
Add `packages: write` to the job's `permissions:` block. This is the most common
|
|
61
|
+
fix and resolves the majority of GHCR push 403 errors:
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
jobs:
|
|
65
|
+
build-and-push:
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
permissions:
|
|
68
|
+
contents: read
|
|
69
|
+
packages: write # Required to push to ghcr.io
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**If login succeeds but push still fails:**
|
|
73
|
+
1. Verify the package is linked to the repository: go to the package on
|
|
74
|
+
`github.com/{owner}/{package}` → Package settings → "Add Repository"
|
|
75
|
+
2. Ensure the package visibility matches the repository (private repo → private
|
|
76
|
+
package, or set the package to public)
|
|
77
|
+
3. For organization repositories, confirm the organization has not blocked
|
|
78
|
+
GitHub Actions from creating packages (Org Settings → Actions → General)
|
|
79
|
+
|
|
80
|
+
**If using a separate PAT or App token:**
|
|
81
|
+
GITHUB_TOKEN with `packages: write` is sufficient for pushing to packages owned
|
|
82
|
+
by the same repository. For cross-repository or org-level package publishing,
|
|
83
|
+
use a Fine-Grained PAT with "Packages: Read and write" scope or a GitHub App
|
|
84
|
+
with "Packages: write" permission.
|
|
85
|
+
fix_code:
|
|
86
|
+
- language: yaml
|
|
87
|
+
label: 'Correct job-level permissions for docker push to ghcr.io'
|
|
88
|
+
code: |
|
|
89
|
+
name: Build and Push Docker Image
|
|
90
|
+
on:
|
|
91
|
+
push:
|
|
92
|
+
branches: [main]
|
|
93
|
+
jobs:
|
|
94
|
+
build-push:
|
|
95
|
+
runs-on: ubuntu-latest
|
|
96
|
+
permissions:
|
|
97
|
+
contents: read
|
|
98
|
+
packages: write # <-- Required for ghcr.io push
|
|
99
|
+
steps:
|
|
100
|
+
- uses: actions/checkout@v4
|
|
101
|
+
|
|
102
|
+
- name: Log in to GitHub Container Registry
|
|
103
|
+
uses: docker/login-action@v3
|
|
104
|
+
with:
|
|
105
|
+
registry: ghcr.io
|
|
106
|
+
username: ${{ github.actor }}
|
|
107
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
108
|
+
|
|
109
|
+
- name: Build and push
|
|
110
|
+
uses: docker/build-push-action@v6
|
|
111
|
+
with:
|
|
112
|
+
context: .
|
|
113
|
+
push: true
|
|
114
|
+
tags: ghcr.io/${{ github.repository }}:latest
|
|
115
|
+
- language: yaml
|
|
116
|
+
label: 'Workflow-level permissions fallback (if setting per-job is not possible)'
|
|
117
|
+
code: |
|
|
118
|
+
name: Build and Push Docker Image
|
|
119
|
+
on:
|
|
120
|
+
push:
|
|
121
|
+
branches: [main]
|
|
122
|
+
|
|
123
|
+
# Set at workflow level — applies to ALL jobs
|
|
124
|
+
permissions:
|
|
125
|
+
contents: read
|
|
126
|
+
packages: write
|
|
127
|
+
|
|
128
|
+
jobs:
|
|
129
|
+
build-push:
|
|
130
|
+
runs-on: ubuntu-latest
|
|
131
|
+
steps:
|
|
132
|
+
- uses: actions/checkout@v4
|
|
133
|
+
- name: Log in to ghcr.io
|
|
134
|
+
uses: docker/login-action@v3
|
|
135
|
+
with:
|
|
136
|
+
registry: ghcr.io
|
|
137
|
+
username: ${{ github.actor }}
|
|
138
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
139
|
+
- name: Push image
|
|
140
|
+
run: |
|
|
141
|
+
docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} .
|
|
142
|
+
docker push ghcr.io/${{ github.repository }}:${{ github.sha }}
|
|
143
|
+
prevention:
|
|
144
|
+
- "Always add `packages: write` to the job permissions block for any job that pushes images to ghcr.io"
|
|
145
|
+
- "Note that docker login to ghcr.io succeeds without packages:write — always test the actual push step to validate permissions"
|
|
146
|
+
- "Check your organization's Actions general settings for any policies that restrict packages creation"
|
|
147
|
+
- "When using docker/build-push-action with push: true, the packages: write permission is required on the job"
|
|
148
|
+
- "For fork PRs, packages: write is unavailable — use conditional steps: `if: github.event.pull_request.head.repo.full_name == github.repository`"
|
|
149
|
+
- "Link the package to its source repository after first creation to enable GITHUB_TOKEN-based pushes in future runs"
|
|
150
|
+
docs:
|
|
151
|
+
- url: 'https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry'
|
|
152
|
+
label: 'GitHub Docs: Working with the Container registry (ghcr.io)'
|
|
153
|
+
- url: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#permissions-for-the-github_token'
|
|
154
|
+
label: 'GitHub Docs: GITHUB_TOKEN permissions reference'
|
|
155
|
+
- url: 'https://stackoverflow.com/questions/70646920/github-token-permission-denied-write-package-when-build-and-push-docker-in-githu'
|
|
156
|
+
label: 'SO #70646920: GITHUB_TOKEN permission denied write_package (22 upvotes, 34k views)'
|
|
157
|
+
- url: 'https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility'
|
|
158
|
+
label: 'GitHub Docs: Configuring a package access control and visibility'
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
id: runner-environment-241
|
|
2
|
+
title: 'Docker container fails with "openat etc/passwd: path escapes from parent" on containerd v2.2+'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- containerd
|
|
7
|
+
- docker
|
|
8
|
+
- healthcheck
|
|
9
|
+
- path-escapes
|
|
10
|
+
- nixos
|
|
11
|
+
- absolute-symlink
|
|
12
|
+
- runner-image-update
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'openat etc/passwd: path escapes from parent'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'openat etc/group: path escapes from parent'
|
|
17
|
+
flags: 'i'
|
|
18
|
+
- regex: 'ExitCode.*-1.*path escapes|path escapes.*ExitCode.*-1'
|
|
19
|
+
flags: 'i'
|
|
20
|
+
- regex: 'mount callback failed.*path escapes from parent'
|
|
21
|
+
flags: 'i'
|
|
22
|
+
error_messages:
|
|
23
|
+
- "openat etc/passwd: path escapes from parent"
|
|
24
|
+
- "openat etc/group: path escapes from parent"
|
|
25
|
+
- "mount callback failed on /tmp/containerd-mount...: openat etc/passwd: path escapes from parent"
|
|
26
|
+
- "ExitCode: -1 (exit code -1)"
|
|
27
|
+
root_cause: |
|
|
28
|
+
containerd v2.2.0+ (built with Go 1.24) introduced stricter path validation via Go 1.24's
|
|
29
|
+
`os.Root` API. When Docker starts or runs a health check on a container whose image has
|
|
30
|
+
`/etc/passwd` or `/etc/group` symlinked to an **absolute path** (e.g., NixOS images where
|
|
31
|
+
`/etc/passwd → /nix/store/.../passwd`), containerd misinterprets the symlink target as
|
|
32
|
+
escaping the container root filesystem and raises:
|
|
33
|
+
`openat etc/passwd: path escapes from parent`.
|
|
34
|
+
|
|
35
|
+
**Affected container images:**
|
|
36
|
+
- **NixOS-based images** (e.g., `nixos/nix:latest`) — `/etc/passwd → /nix/store/.../passwd`
|
|
37
|
+
- **ngrok container images** — use absolute symlinks for system files
|
|
38
|
+
- **Android emulator images** — `/etc` itself may be an absolute symlink to `/system/etc`
|
|
39
|
+
- Any image where the symlink target for `/etc/passwd` or `/etc/group` starts with `/`
|
|
40
|
+
|
|
41
|
+
**Impact on GitHub Actions workflows:**
|
|
42
|
+
1. Service containers with HEALTHCHECK definitions fail with `ExitCode: -1` even when the
|
|
43
|
+
service is actually running correctly
|
|
44
|
+
2. Container jobs (`container: image: nixos/nix:latest`) fail at startup before any steps run
|
|
45
|
+
3. Docker `run` steps using affected images fail with `path escapes from parent` in logs
|
|
46
|
+
|
|
47
|
+
**Status on GitHub-hosted runners:**
|
|
48
|
+
- **Windows runners** (windows-2022, windows-2025, windows-11-arm64): containerd v2.2.x
|
|
49
|
+
shipped with Docker 29 on February 9, 2026 — **currently affected**
|
|
50
|
+
- **Ubuntu runners**: containerd v2.2.x deployed February 9, 2026 then **rolled back on
|
|
51
|
+
February 20, 2026** due to this and related issues (runner-images#13682, #13684, #13691);
|
|
52
|
+
tracked for re-deployment in runner-images#14105
|
|
53
|
+
|
|
54
|
+
A partial fix was merged in containerd v2.2.2 (commit 85b5418e) addressing the case where
|
|
55
|
+
`/etc/passwd` itself is a direct absolute symlink. However, the case where an **intermediate
|
|
56
|
+
directory** (e.g., `/etc` is an absolute symlink to `/system/etc`) remains broken and open
|
|
57
|
+
in containerd#13382 as of May 2026.
|
|
58
|
+
|
|
59
|
+
Source: actions/runner-images#13682 (Feb 2026), containerd/containerd#12683,
|
|
60
|
+
reubeno/brush#999 (real-world GitHub Actions failure)
|
|
61
|
+
fix: |
|
|
62
|
+
**Option 1 — Convert absolute symlinks to relative in a pre-step (most portable fix):**
|
|
63
|
+
Add a step before any Docker operations that resolves absolute `/etc/passwd` and
|
|
64
|
+
`/etc/group` symlinks to relative equivalents inside the container. This approach works
|
|
65
|
+
even when you cannot modify the container image.
|
|
66
|
+
|
|
67
|
+
**Option 2 — Build a derived image with relative symlinks:**
|
|
68
|
+
Create a `Dockerfile` that `FROM` the affected image and replaces the absolute symlinks
|
|
69
|
+
with relative ones. This is the most reliable long-term fix when you own the workflow.
|
|
70
|
+
|
|
71
|
+
**Option 3 — Use an alternative image without absolute symlinks:**
|
|
72
|
+
Standard Ubuntu, Debian, and Alpine images use regular files (not symlinks) for
|
|
73
|
+
`/etc/passwd` and `/etc/group` — they are unaffected. If the workflow can use a
|
|
74
|
+
different base image, this sidesteps the issue entirely.
|
|
75
|
+
|
|
76
|
+
**Option 4 — Pin containerd to v2.1.x on self-hosted runners:**
|
|
77
|
+
On self-hosted runners where you control Docker/containerd versions, remain on
|
|
78
|
+
containerd v1.7.x or v2.1.x until containerd v2.2.3+ resolves all absolute symlink cases.
|
|
79
|
+
fix_code:
|
|
80
|
+
- language: yaml
|
|
81
|
+
label: 'Workaround — convert absolute /etc symlinks in a pre-step (NixOS/ngrok containers)'
|
|
82
|
+
code: |
|
|
83
|
+
jobs:
|
|
84
|
+
test:
|
|
85
|
+
runs-on: ubuntu-latest
|
|
86
|
+
container:
|
|
87
|
+
image: nixos/nix:latest
|
|
88
|
+
steps:
|
|
89
|
+
- name: Fix absolute /etc symlinks (containerd v2.2+ workaround)
|
|
90
|
+
run: |
|
|
91
|
+
for f in /etc/passwd /etc/group; do
|
|
92
|
+
if [ -L "$f" ]; then
|
|
93
|
+
target=$(readlink "$f")
|
|
94
|
+
if echo "$target" | grep -q '^/'; then
|
|
95
|
+
# Convert absolute symlink to relative
|
|
96
|
+
rel=$(python3 -c "import os; print(os.path.relpath('$target', '/etc'))")
|
|
97
|
+
ln -sf "$rel" "$f"
|
|
98
|
+
fi
|
|
99
|
+
fi
|
|
100
|
+
done
|
|
101
|
+
- name: Run tests
|
|
102
|
+
run: nix run nixpkgs#hello
|
|
103
|
+
|
|
104
|
+
- language: yaml
|
|
105
|
+
label: 'Build a derived image that replaces absolute symlinks with relative ones'
|
|
106
|
+
code: |
|
|
107
|
+
# Dockerfile.fixed — used for CI to avoid the containerd v2.2 regression:
|
|
108
|
+
# FROM nixos/nix:latest
|
|
109
|
+
# RUN for f in /etc/passwd /etc/group; do \
|
|
110
|
+
# if [ -L "$f" ]; then \
|
|
111
|
+
# target=$(readlink "$f"); \
|
|
112
|
+
# rel=$(python3 -c "import os; print(os.path.relpath('$target', '/etc'))"); \
|
|
113
|
+
# ln -sf "$rel" "$f"; \
|
|
114
|
+
# fi; \
|
|
115
|
+
# done
|
|
116
|
+
|
|
117
|
+
# In workflow — build derived image first:
|
|
118
|
+
steps:
|
|
119
|
+
- name: Build patched image
|
|
120
|
+
run: docker build -f Dockerfile.fixed -t my-nix-fixed .
|
|
121
|
+
|
|
122
|
+
- name: Use patched image
|
|
123
|
+
run: docker run --rm my-nix-fixed nix run nixpkgs#hello
|
|
124
|
+
|
|
125
|
+
- language: yaml
|
|
126
|
+
label: 'Use Alpine or Debian service container instead of NixOS/ngrok'
|
|
127
|
+
code: |
|
|
128
|
+
# Unaffected base images (no absolute symlinks for /etc/passwd):
|
|
129
|
+
# redis:7-alpine, postgres:16-alpine, debian:bookworm-slim, ubuntu:24.04
|
|
130
|
+
jobs:
|
|
131
|
+
test:
|
|
132
|
+
runs-on: windows-2025 # Docker 29 + containerd v2.2 — always active on Windows
|
|
133
|
+
services:
|
|
134
|
+
redis:
|
|
135
|
+
image: redis:7-alpine
|
|
136
|
+
options: >-
|
|
137
|
+
--health-cmd "redis-cli ping"
|
|
138
|
+
--health-interval 10s
|
|
139
|
+
--health-timeout 5s
|
|
140
|
+
--health-retries 5
|
|
141
|
+
prevention:
|
|
142
|
+
- 'Never use NixOS, ngrok, or Android emulator container images as service containers on Windows runners without the absolute-symlink workaround — Windows runners have had containerd v2.2.x since Feb 2026.'
|
|
143
|
+
- 'Check if your container image uses absolute /etc/passwd symlinks with: `docker run --rm <image> readlink /etc/passwd`. If the output starts with "/", it will fail on containerd v2.2+.'
|
|
144
|
+
- 'Use official distribution base images (Alpine, Debian, Ubuntu) for service containers when possible — they use regular files for /etc/passwd and are unaffected.'
|
|
145
|
+
- 'Monitor runner-images#14105 for the Ubuntu Docker 29 re-deployment timeline — once Ubuntu runners re-deploy Docker 29, this issue will re-appear on Linux jobs as well.'
|
|
146
|
+
docs:
|
|
147
|
+
- url: 'https://github.com/actions/runner-images/issues/13682'
|
|
148
|
+
label: 'runner-images#13682 — Container healthchecks failing with path escapes on Ubuntu runners'
|
|
149
|
+
- url: 'https://github.com/containerd/containerd/issues/12683'
|
|
150
|
+
label: 'containerd#12683 — v2.2.0 fails to create containers with /etc/passwd as absolute symlink'
|
|
151
|
+
- url: 'https://github.com/containerd/containerd/issues/13382'
|
|
152
|
+
label: 'containerd#13382 — v2.2+ fails when /etc directory itself is an absolute symlink'
|
|
153
|
+
- url: 'https://github.com/reubeno/brush/issues/999'
|
|
154
|
+
label: 'brush#999 — Real-world GitHub Actions failure with nixos/nix container'
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
id: runner-environment-242
|
|
2
|
+
title: 'Docker Engine v29 raises minimum API to 1.44 — old SDK clients fail with "client version X is too old"'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- docker
|
|
7
|
+
- docker-29
|
|
8
|
+
- api-version
|
|
9
|
+
- sdk
|
|
10
|
+
- windows
|
|
11
|
+
- runner-image-update
|
|
12
|
+
- python-docker
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'client version \d+\.\d+ is too old\. Minimum supported API version is 1\.4[4-9]'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'Error response from daemon: client version.*Minimum supported API version is 1\.4[4-9]'
|
|
17
|
+
flags: 'i'
|
|
18
|
+
- regex: 'minimum supported API version.*1\.4[4-9]|API version.*too old.*upgrade your client'
|
|
19
|
+
flags: 'i'
|
|
20
|
+
error_messages:
|
|
21
|
+
- "Error response from daemon: client version 1.41 is too old. Minimum supported API version is 1.44, please upgrade your client to a newer version"
|
|
22
|
+
- "Error response from daemon: client version 1.43 is too old. Minimum supported API version is 1.44, please upgrade your client to a newer version"
|
|
23
|
+
- "Error response from daemon: client version 1.24 is too old. Minimum supported API version is 1.44, please upgrade your client to a newer version"
|
|
24
|
+
root_cause: |
|
|
25
|
+
Docker Engine v29.0 (released November 2025) raised the **minimum supported Docker daemon
|
|
26
|
+
API version from 1.24 to 1.44**. Any Docker SDK client that negotiates API version 1.43 or
|
|
27
|
+
lower receives:
|
|
28
|
+
`"Error response from daemon: client version 1.41 is too old. Minimum supported API version
|
|
29
|
+
is 1.44, please upgrade your client to a newer version"`.
|
|
30
|
+
|
|
31
|
+
**API version 1.44 corresponds to Docker Engine 23.0**. Any SDK client built against Docker
|
|
32
|
+
< 23.0 will fail when the daemon is Docker Engine v29+.
|
|
33
|
+
|
|
34
|
+
**Impact on GitHub Actions — current status:**
|
|
35
|
+
- **Windows runners** (windows-2022, windows-2025, windows-11-arm64): Docker 29.x deployed
|
|
36
|
+
February 9, 2026 — **currently affected on Windows workflows**
|
|
37
|
+
- **Ubuntu runners**: Docker 29.x rolled back February 20, 2026 due to related issues
|
|
38
|
+
(runner-images#13682, #13684); re-deployment tracked in runner-images#14105
|
|
39
|
+
|
|
40
|
+
**Affected tools and workflows:**
|
|
41
|
+
- Python `docker` library ≤ 6.1.3 (negotiates API 1.41 by default) — upgrade to ≥ 7.0.0
|
|
42
|
+
- `google/oss-fuzz` CIFuzz action — uses internal Python docker client negotiating API 1.41;
|
|
43
|
+
affected every project using `google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master`
|
|
44
|
+
- Go `github.com/docker/docker/client` packages pinned to Docker < 23.0 API
|
|
45
|
+
- Any workflow tool, action, or custom script that embeds its own Docker SDK rather than
|
|
46
|
+
invoking the CLI `docker` command
|
|
47
|
+
- GitHub Codespaces dev container CI workflows using Docker SDK library in test scripts
|
|
48
|
+
|
|
49
|
+
**Note:** This is distinct from the Docker Compose v1/v2 breaking changes (see
|
|
50
|
+
`docker-29-compose-v2-40-breaking.yml` / re-031), which covers Compose CLI changes.
|
|
51
|
+
This entry covers SDK API negotiation failures from non-CLI Docker clients.
|
|
52
|
+
|
|
53
|
+
Source: google/oss-fuzz#14945 (Feb 2026), actions/runner-images#13474, docker/docs#23910
|
|
54
|
+
fix: |
|
|
55
|
+
**Option 1 — Upgrade Python docker library to ≥ 7.0.0:**
|
|
56
|
+
The most common case. Python docker SDK ≥ 7.0.0 negotiates API 1.47+ which is compatible
|
|
57
|
+
with Docker Engine 29.
|
|
58
|
+
|
|
59
|
+
**Option 2 — Use the Docker CLI instead of SDK calls:**
|
|
60
|
+
Replace Python/Go SDK calls with `docker build`, `docker run`, etc. via `run:` steps. The
|
|
61
|
+
Docker CLI always negotiates the correct API version with the daemon automatically.
|
|
62
|
+
|
|
63
|
+
**Option 3 — Set DOCKER_API_VERSION environment variable:**
|
|
64
|
+
Some SDKs honor `DOCKER_API_VERSION=1.44` as an override. However this only works if the
|
|
65
|
+
SDK actually implements the 1.44 protocol — just setting the env var won't upgrade an
|
|
66
|
+
SDK that doesn't support 1.44.
|
|
67
|
+
|
|
68
|
+
**Option 4 — Pin the affected tool to an updated version:**
|
|
69
|
+
For CIFuzz: the fix was deployed to `google/oss-fuzz` within hours of the issue being
|
|
70
|
+
reported. Pin `@master` to get the fix, or wait for a tagged release. For any other
|
|
71
|
+
action/tool embedding Docker SDK, check for an updated release that bumps the SDK.
|
|
72
|
+
fix_code:
|
|
73
|
+
- language: yaml
|
|
74
|
+
label: 'Upgrade Python docker SDK in workflow before using it'
|
|
75
|
+
code: |
|
|
76
|
+
# The error appears in workflows using Python docker library <= 6.1.3
|
|
77
|
+
# Example error:
|
|
78
|
+
# Error response from daemon: client version 1.41 is too old.
|
|
79
|
+
# Minimum supported API version is 1.44
|
|
80
|
+
steps:
|
|
81
|
+
- name: Upgrade Docker Python SDK
|
|
82
|
+
run: pip install 'docker>=7.0.0'
|
|
83
|
+
|
|
84
|
+
- name: Run Docker-based tests
|
|
85
|
+
run: python -m pytest tests/docker/
|
|
86
|
+
|
|
87
|
+
- language: yaml
|
|
88
|
+
label: 'Replace SDK docker.from_env() calls with Docker CLI'
|
|
89
|
+
code: |
|
|
90
|
+
# Instead of Python SDK:
|
|
91
|
+
# import docker
|
|
92
|
+
# client = docker.from_env()
|
|
93
|
+
# client.images.build(path='.', tag='my-image')
|
|
94
|
+
# Use the CLI directly via shell steps:
|
|
95
|
+
steps:
|
|
96
|
+
- name: Build Docker image
|
|
97
|
+
run: docker build -t my-image:latest .
|
|
98
|
+
|
|
99
|
+
- name: Run container
|
|
100
|
+
run: docker run --rm my-image:latest ./run-tests.sh
|
|
101
|
+
|
|
102
|
+
- name: Push to registry
|
|
103
|
+
run: docker push my-image:latest
|
|
104
|
+
|
|
105
|
+
- language: yaml
|
|
106
|
+
label: 'Check Docker API version compatibility in your workflow'
|
|
107
|
+
code: |
|
|
108
|
+
# Run this step to diagnose version negotiation issues:
|
|
109
|
+
steps:
|
|
110
|
+
- name: Show Docker version information
|
|
111
|
+
run: |
|
|
112
|
+
docker version
|
|
113
|
+
# Server.APIVersion: 1.47 (what the daemon offers)
|
|
114
|
+
# Client.APIVersion: 1.47 (what the CLI uses — always current)
|
|
115
|
+
# If using Python sdk: python3 -c "import docker; c=docker.from_env(); print(c.version())"
|
|
116
|
+
# If sdk prints error about client version, upgrade docker>=7.0.0
|
|
117
|
+
prevention:
|
|
118
|
+
- 'Avoid embedding Docker SDK client calls in workflow scripts — always prefer the Docker CLI via run: steps, which auto-negotiates the correct API version.'
|
|
119
|
+
- 'When the Python docker library IS required, pin it to >=7.0.0 in requirements.txt or install it explicitly in a workflow step before use.'
|
|
120
|
+
- 'Test workflows on windows-2025 before ubuntu re-deployment of Docker 29 — Windows runners already expose the Docker 29 min API 1.44 constraint.'
|
|
121
|
+
- 'If using google/oss-fuzz CIFuzz, ensure you reference a recent commit — the fix for API 1.41 incompatibility was deployed in Feb 2026.'
|
|
122
|
+
- 'When adding new tool dependencies that use Docker, check the docker-py version they require and whether it supports API >= 1.44.'
|
|
123
|
+
docs:
|
|
124
|
+
- url: 'https://github.com/google/oss-fuzz/issues/14945'
|
|
125
|
+
label: 'oss-fuzz#14945 — CIFuzz fails with client version 1.41 too old after Docker v29 update'
|
|
126
|
+
- url: 'https://github.com/actions/runner-images/issues/13474'
|
|
127
|
+
label: 'runner-images#13474 — Docker 29.1.* update announcement (Feb 9, 2026)'
|
|
128
|
+
- url: 'https://docs.docker.com/reference/api/engine/'
|
|
129
|
+
label: 'Docker Engine API reference — version compatibility matrix'
|
|
130
|
+
- url: 'https://github.com/actions/runner-images/issues/14105'
|
|
131
|
+
label: 'runner-images#14105 — Docker v29 Ubuntu re-deployment tracking issue'
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
id: runner-environment-243
|
|
2
|
+
title: 'macOS 26 runner — Xcode_26.0.app path does not exist; only Xcode_26.0.1.app is installed'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- macos-26
|
|
7
|
+
- xcode
|
|
8
|
+
- xcode-select
|
|
9
|
+
- sdk-not-found
|
|
10
|
+
- runner-image
|
|
11
|
+
- ios
|
|
12
|
+
- version-naming
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'SDK.*Xcode_26\.0\.app.*cannot be located|Xcode_26\.0\.app.*SDK.*cannot be located'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'xcode-select.*Xcode_26\.0\.app.*no such file|invalid developer directory.*Xcode_26\.0\.app'
|
|
17
|
+
flags: 'i'
|
|
18
|
+
- regex: 'xcodebuild: error: SDK.*Xcode_26\.0[^.1].*cannot be located'
|
|
19
|
+
flags: 'i'
|
|
20
|
+
- regex: '/Applications/Xcode_26\.0\.app.*does not exist'
|
|
21
|
+
flags: 'i'
|
|
22
|
+
error_messages:
|
|
23
|
+
- "xcodebuild: error: SDK \"/Applications/Xcode_26.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk\" cannot be located."
|
|
24
|
+
- "xcode-select: error: invalid developer directory '/Applications/Xcode_26.0.app/Contents/Developer'"
|
|
25
|
+
- "error: '/Applications/Xcode_26.0.app' does not exist or is not a directory"
|
|
26
|
+
root_cause: |
|
|
27
|
+
On `macos-26` and `macos-26-arm64` runners, Xcode applications are installed with their
|
|
28
|
+
**full version number including patch** in the directory name:
|
|
29
|
+
- `Xcode_26.0.1.app` — NOT `Xcode_26.0.app`
|
|
30
|
+
- `Xcode_26.2.app`
|
|
31
|
+
- `Xcode_26.4.1.app` — NOT `Xcode_26.4.app`
|
|
32
|
+
|
|
33
|
+
Workflows that hardcode `/Applications/Xcode_26.0.app` in `xcode-select --switch` or in
|
|
34
|
+
`DEVELOPER_DIR` environment variables fail immediately because the path does not exist.
|
|
35
|
+
No backward-compatible symlink (`Xcode_26.0.app → Xcode_26.0.1.app`) is created.
|
|
36
|
+
|
|
37
|
+
**Why this changed:** Starting with Xcode 26, Apple's versioning scheme includes a patch
|
|
38
|
+
component (major.minor.patch) that is reflected in the installed application directory name
|
|
39
|
+
when the patch is non-zero. This differs from Xcode 16 and earlier where the directory name
|
|
40
|
+
omitted the patch (e.g., `Xcode_16.4.app` is actually Xcode 16.4.0).
|
|
41
|
+
|
|
42
|
+
**Note on the "26.0" naming gap:** The first generally-available Xcode for macOS 26 was
|
|
43
|
+
Xcode 26.0.1 (not 26.0.0). This means `Xcode_26.0.app` was never installed — the runner
|
|
44
|
+
image went straight from having no Xcode 26 to having `Xcode_26.0.1.app`.
|
|
45
|
+
|
|
46
|
+
Source: actions/runner-images#13743 (Feb 2026)
|
|
47
|
+
fix: |
|
|
48
|
+
**Option 1 — Use maxim-lobanov/setup-xcode action (recommended):**
|
|
49
|
+
This action resolves Xcode paths dynamically from the runner's installed versions and
|
|
50
|
+
handles the naming scheme automatically. Specify an exact version like `'26.0.1'` or
|
|
51
|
+
`'latest-stable'`.
|
|
52
|
+
|
|
53
|
+
**Option 2 — Hardcode the full version including patch:**
|
|
54
|
+
Replace `Xcode_26.0.app` with `Xcode_26.0.1.app`. Always check the runner image Readme
|
|
55
|
+
for the exact installed filename before pinning.
|
|
56
|
+
|
|
57
|
+
**Option 3 — List available versions at runtime:**
|
|
58
|
+
Add a discovery step that lists `/Applications/Xcode*.app/` and uses the result to
|
|
59
|
+
select the correct version dynamically.
|
|
60
|
+
fix_code:
|
|
61
|
+
- language: yaml
|
|
62
|
+
label: 'Use setup-xcode to resolve Xcode path automatically (recommended)'
|
|
63
|
+
code: |
|
|
64
|
+
# setup-xcode handles the naming scheme and patches for you
|
|
65
|
+
jobs:
|
|
66
|
+
build-ios:
|
|
67
|
+
runs-on: macos-26
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4
|
|
70
|
+
|
|
71
|
+
- uses: maxim-lobanov/setup-xcode@v1
|
|
72
|
+
with:
|
|
73
|
+
xcode-version: '26.0.1' # full version including patch
|
|
74
|
+
|
|
75
|
+
- name: Build
|
|
76
|
+
run: xcodebuild -scheme MyApp -destination generic/platform=iOS build
|
|
77
|
+
|
|
78
|
+
- language: yaml
|
|
79
|
+
label: 'Pin correct full-patch version in xcode-select --switch'
|
|
80
|
+
code: |
|
|
81
|
+
# Wrong — path does not exist on macos-26:
|
|
82
|
+
# - run: sudo xcode-select --switch /Applications/Xcode_26.0.app/Contents/Developer
|
|
83
|
+
|
|
84
|
+
# Correct — include the patch version:
|
|
85
|
+
jobs:
|
|
86
|
+
build-ios:
|
|
87
|
+
runs-on: macos-26
|
|
88
|
+
steps:
|
|
89
|
+
- name: Select Xcode 26.0.1
|
|
90
|
+
run: sudo xcode-select --switch /Applications/Xcode_26.0.1.app/Contents/Developer
|
|
91
|
+
|
|
92
|
+
- name: Verify Xcode version
|
|
93
|
+
run: xcodebuild -version
|
|
94
|
+
|
|
95
|
+
- language: yaml
|
|
96
|
+
label: 'Discover installed Xcode versions at runtime'
|
|
97
|
+
code: |
|
|
98
|
+
# Add a discovery step to find what is actually installed:
|
|
99
|
+
steps:
|
|
100
|
+
- name: List installed Xcode versions
|
|
101
|
+
run: |
|
|
102
|
+
echo "Available Xcode installations:"
|
|
103
|
+
ls -la /Applications/Xcode*.app/ 2>/dev/null | awk '{print $NF}'
|
|
104
|
+
echo ""
|
|
105
|
+
echo "Currently selected Xcode:"
|
|
106
|
+
xcode-select -p
|
|
107
|
+
xcodebuild -version
|
|
108
|
+
|
|
109
|
+
prevention:
|
|
110
|
+
- 'Never hardcode Xcode application directory paths — use maxim-lobanov/setup-xcode@v1 with a specific xcode-version that includes the patch number.'
|
|
111
|
+
- 'When pinning a path is required, always look up the exact installed path in the runner image Readme: https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md#xcode'
|
|
112
|
+
- 'For Xcode 26.x, always include the patch in version strings: "26.0.1" not "26.0", "26.4.1" not "26.4".'
|
|
113
|
+
- 'Subscribe to runner-images announcements to get advance notice of Xcode version updates that change installed paths.'
|
|
114
|
+
docs:
|
|
115
|
+
- url: 'https://github.com/actions/runner-images/issues/13743'
|
|
116
|
+
label: 'runner-images#13743 — Xcode 26.0 symlink not working on macos-26 (Feb 2026)'
|
|
117
|
+
- url: 'https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md'
|
|
118
|
+
label: 'macOS 26 arm64 runner image Readme — installed Xcode versions'
|
|
119
|
+
- url: 'https://github.com/maxim-lobanov/setup-xcode'
|
|
120
|
+
label: 'maxim-lobanov/setup-xcode — recommended action for Xcode version selection'
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
id: runner-environment-244
|
|
2
|
+
title: 'macOS 26 — iOS/watchOS/tvOS 26.0 simulator runtimes removed when Xcode 26.4 GA deployed'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- macos-26
|
|
7
|
+
- xcode
|
|
8
|
+
- ios-simulator
|
|
9
|
+
- simulator-runtime
|
|
10
|
+
- xcodebuild
|
|
11
|
+
- runtime-removed
|
|
12
|
+
- runner-image-update
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'Unable to find a destination matching the provided destination specifier.*OS:26\.0[^.]'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'Unable to boot.*Simulator.*26\.0[^.].*unavailable|The destination.*iOS.*26\.0[^.].*not available'
|
|
17
|
+
flags: 'i'
|
|
18
|
+
- regex: 'Could not find a simulator runtime for.*26\.0[^.]|No matching destinations for.*OS.*26\.0'
|
|
19
|
+
flags: 'i'
|
|
20
|
+
- regex: 'simulator.*OS=26\.0[^.][^0-9].*not found|destination.*platform=iOS Simulator.*OS:26\.0[^.].*unavailable'
|
|
21
|
+
flags: 'i'
|
|
22
|
+
error_messages:
|
|
23
|
+
- "xcodebuild: error: Unable to find a destination matching the provided destination specifier: { platform:iOS Simulator, OS:26.0 }"
|
|
24
|
+
- "Unable to boot the Simulator. The request to boot 'iOS 26.0 Simulator' was denied because the destination is incompatible with this version of Xcode."
|
|
25
|
+
- "Could not find a simulator runtime for 'iOS 26.0'"
|
|
26
|
+
- "No matching destinations for { platform:iOS Simulator, OS:26.0 }"
|
|
27
|
+
root_cause: |
|
|
28
|
+
On April 1, 2026, GitHub merged runner-images PR #13875 which moved Xcode 26.4 from Release
|
|
29
|
+
Candidate to GA on `macos-26` and `macos-26-arm64` runner images. As part of this change:
|
|
30
|
+
|
|
31
|
+
- **Added:** iOS 26.4, watchOS 26.4, tvOS 26.4, visionOS 26.4 simulator runtimes
|
|
32
|
+
- **Removed:** iOS 26.0.1, watchOS 26.0.1, tvOS 26.0.1, visionOS 26.0.1 simulator runtimes
|
|
33
|
+
|
|
34
|
+
GitHub Actions images support **at most three runtime sets per Xcode** due to disk space
|
|
35
|
+
constraints (documented in macos-15-xcode-simulator-sdk-policy.yml). When a new runtime set
|
|
36
|
+
is added, the oldest is removed.
|
|
37
|
+
|
|
38
|
+
**Affected workflows:**
|
|
39
|
+
- Workflows that pin `OS:26.0` in xcodebuild `-destination` strings (e.g.,
|
|
40
|
+
`-destination 'platform=iOS Simulator,name=iPhone 16,OS=26.0'`)
|
|
41
|
+
- Workflows using `xcrun simctl list runtimes` that previously found `iOS 26.0` and now
|
|
42
|
+
find only `iOS 26.2` and `iOS 26.4` (or later versions)
|
|
43
|
+
- `fastlane scan` or similar tools configured with a hardcoded iOS 26.0 simulator target
|
|
44
|
+
- Any tooling that generates test matrices including `iOS 26.0` destinations
|
|
45
|
+
|
|
46
|
+
Simulator runtimes **currently available** on macos-26 after the April 1 change:
|
|
47
|
+
- iOS 26.2 + watchOS 26.2 + tvOS 26.2 + visionOS 26.2
|
|
48
|
+
- iOS 26.4 + watchOS 26.4 + tvOS 26.4 + visionOS 26.4
|
|
49
|
+
(The exact installed runtimes change with each Xcode GA deployment. Always check the runner
|
|
50
|
+
image Readme for the current set.)
|
|
51
|
+
|
|
52
|
+
Source: actions/runner-images PR #13875 (merged April 1, 2026), runner-images#13853
|
|
53
|
+
fix: |
|
|
54
|
+
**Option 1 — Update destination to use an available runtime version:**
|
|
55
|
+
Replace `OS:26.0` with `OS:26.4` (or `latest-available`) in xcodebuild destination strings.
|
|
56
|
+
Pin to a specific available version to avoid future breakage.
|
|
57
|
+
|
|
58
|
+
**Option 2 — Use `latest-available` as the OS version:**
|
|
59
|
+
Some xcodebuild invocations accept `OS:latest-available` as the OS specifier, which picks
|
|
60
|
+
the newest installed runtime matching the platform. This avoids hard-coding a version.
|
|
61
|
+
|
|
62
|
+
**Option 3 — Use the maxim-lobanov/setup-ios-simulator action:**
|
|
63
|
+
This action can download and install a specific simulator runtime on demand, decoupling
|
|
64
|
+
your workflow from what is pre-installed on the runner image.
|
|
65
|
+
|
|
66
|
+
**Option 4 — Query available runtimes at runtime and select dynamically:**
|
|
67
|
+
Use `xcrun simctl list runtimes` to discover what is installed before running tests, then
|
|
68
|
+
construct the `-destination` argument from the actual available runtimes.
|
|
69
|
+
fix_code:
|
|
70
|
+
- language: yaml
|
|
71
|
+
label: 'Update destination to latest available simulator runtime'
|
|
72
|
+
code: |
|
|
73
|
+
jobs:
|
|
74
|
+
test-ios:
|
|
75
|
+
runs-on: macos-26
|
|
76
|
+
steps:
|
|
77
|
+
- uses: actions/checkout@v4
|
|
78
|
+
|
|
79
|
+
- uses: maxim-lobanov/setup-xcode@v1
|
|
80
|
+
with:
|
|
81
|
+
xcode-version: 'latest-stable'
|
|
82
|
+
|
|
83
|
+
# Wrong — iOS 26.0 runtime no longer installed:
|
|
84
|
+
# - run: xcodebuild test -scheme MyApp
|
|
85
|
+
# -destination 'platform=iOS Simulator,name=iPhone 16,OS=26.0'
|
|
86
|
+
|
|
87
|
+
# Correct — use an installed runtime version:
|
|
88
|
+
- name: Run iOS tests
|
|
89
|
+
run: |
|
|
90
|
+
xcodebuild test \
|
|
91
|
+
-scheme MyApp \
|
|
92
|
+
-destination 'platform=iOS Simulator,name=iPhone 16,OS=26.4'
|
|
93
|
+
|
|
94
|
+
- language: yaml
|
|
95
|
+
label: 'Use latest-available OS version to avoid future runtime removals'
|
|
96
|
+
code: |
|
|
97
|
+
# latest-available picks the newest installed runtime automatically:
|
|
98
|
+
steps:
|
|
99
|
+
- name: Run iOS tests
|
|
100
|
+
run: |
|
|
101
|
+
xcodebuild test \
|
|
102
|
+
-scheme MyApp \
|
|
103
|
+
-destination 'platform=iOS Simulator,name=iPhone 16,OS=latest-available'
|
|
104
|
+
|
|
105
|
+
- language: yaml
|
|
106
|
+
label: 'Discover installed simulator runtimes before running tests'
|
|
107
|
+
code: |
|
|
108
|
+
# Add a diagnostic step to see what runtimes are available:
|
|
109
|
+
steps:
|
|
110
|
+
- name: List installed simulator runtimes
|
|
111
|
+
run: xcrun simctl list runtimes
|
|
112
|
+
|
|
113
|
+
# Example output after April 2026:
|
|
114
|
+
# == Runtimes ==
|
|
115
|
+
# iOS 26.2 (26.2) - com.apple.CoreSimulator.SimRuntime.iOS-26-2
|
|
116
|
+
# iOS 26.4 (26.4) - com.apple.CoreSimulator.SimRuntime.iOS-26-4
|
|
117
|
+
# watchOS 26.2 ...
|
|
118
|
+
# (iOS 26.0 is NO LONGER listed)
|
|
119
|
+
|
|
120
|
+
- name: Run tests against iOS 26.4
|
|
121
|
+
run: |
|
|
122
|
+
xcodebuild test \
|
|
123
|
+
-scheme MyApp \
|
|
124
|
+
-destination 'platform=iOS Simulator,name=iPhone 16,OS=26.4'
|
|
125
|
+
prevention:
|
|
126
|
+
- 'Never hardcode specific iOS/watchOS/tvOS simulator runtime version numbers in xcodebuild destination strings — use OS:latest-available or dynamically query installed runtimes.'
|
|
127
|
+
- 'Check the macOS runner image Readme before each Xcode GA update to verify which simulator runtime sets are installed: https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md'
|
|
128
|
+
- 'Subscribe to runner-images announcements and PRs that add new Xcode GA versions — they always remove the oldest simulator runtime set.'
|
|
129
|
+
- 'If you need to test against a specific older runtime, use maxim-lobanov/setup-ios-simulator to download it on demand rather than relying on pre-installed runtimes.'
|
|
130
|
+
docs:
|
|
131
|
+
- url: 'https://github.com/actions/runner-images/pull/13875'
|
|
132
|
+
label: 'runner-images PR #13875 — Xcode 26.4 GA: added 26.4 runtimes, removed 26.0.1 runtimes'
|
|
133
|
+
- url: 'https://github.com/actions/runner-images/issues/13853'
|
|
134
|
+
label: 'runner-images#13853 — macos-26-arm64 Xcode 26.4 RC missing iOS 26.4 simulator runtime'
|
|
135
|
+
- url: 'https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md'
|
|
136
|
+
label: 'macOS 26 arm64 runner image Readme — installed simulators section'
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
id: runner-environment-245
|
|
2
|
+
title: 'ARC ephemeral runner pod hangs indefinitely after workflow job cancellation — "Skipping message Job. Job message not found ... job was canceled"'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- arc
|
|
7
|
+
- kubernetes
|
|
8
|
+
- ephemeral-runner
|
|
9
|
+
- cancellation
|
|
10
|
+
- stuck-runner
|
|
11
|
+
- gha-runner-scale-set
|
|
12
|
+
- job-canceled
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'Skipping message Job\. Job message not found .+ job was canceled'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'EphemeralRunner.*status.*Running.*canceled'
|
|
17
|
+
flags: 'i'
|
|
18
|
+
- regex: 'Registration .+ was not found\.'
|
|
19
|
+
flags: 'i'
|
|
20
|
+
- regex: 'POST request to .+acquirejob failed\. HTTP Status: Conflict'
|
|
21
|
+
flags: 'i'
|
|
22
|
+
error_messages:
|
|
23
|
+
- "Skipping message Job. Job message not found 'e420db7b-c780-5ae4-8145-4eea09b87aea'. job was canceled"
|
|
24
|
+
- "POST request to https://run-actions-*.actions.githubusercontent.com/*/acquirejob failed. HTTP Status: Conflict"
|
|
25
|
+
- "Registration 470d6c87-f8c4-411f-87d0-6b069233ccc7 was not found."
|
|
26
|
+
root_cause: |
|
|
27
|
+
When a GitHub Actions workflow job is canceled (manually or by concurrency group
|
|
28
|
+
cancellation) while an ARC ephemeral runner is in the process of starting up or
|
|
29
|
+
acquiring the job message, the runner pod enters a broken state:
|
|
30
|
+
|
|
31
|
+
1. The broker sends a "job was canceled" message on the runner's job socket.
|
|
32
|
+
2. The runner logs: "Skipping message Job. Job message not found 'X'. job was canceled"
|
|
33
|
+
3. **The runner process does not exit** — it waits for a new job message that
|
|
34
|
+
will never arrive, because ephemeral runners are single-use and the broker
|
|
35
|
+
considers this runner's slot exhausted.
|
|
36
|
+
4. The ARC controller sees the EphemeralRunner pod still in `Running` phase with
|
|
37
|
+
a live runner process. It does NOT delete and recreate the pod.
|
|
38
|
+
5. The runner slot is held indefinitely. No new job can be dispatched to this slot.
|
|
39
|
+
Workflows queue but cannot start, consuming queue capacity without making progress.
|
|
40
|
+
|
|
41
|
+
**Secondary failure mode**: After the canceled-job hang, the runner may also
|
|
42
|
+
attempt to re-acquire its registration token. Since the ephemeral runner's
|
|
43
|
+
registration was already consumed or expired, this fails with:
|
|
44
|
+
`Registration 'X' was not found.`
|
|
45
|
+
The BrokerServer then throws repeatedly, producing a growing error log.
|
|
46
|
+
|
|
47
|
+
**Impact**: In a scale set with `minRunners > 0`, each canceled job permanently
|
|
48
|
+
removes one runner slot from the pool until the pod is manually deleted or the
|
|
49
|
+
scale set is bounced. With frequent cancellations (e.g., PR pushes with concurrency
|
|
50
|
+
cancel-in-progress), the pool drains completely and CI halts.
|
|
51
|
+
|
|
52
|
+
Source: actions/actions-runner-controller#4307 (Nov 2025, 11 reactions, open).
|
|
53
|
+
Also related: ARC#4468 (scale set queuing delay during burst) — adjacent but distinct.
|
|
54
|
+
fix: |
|
|
55
|
+
**Option 1 — Delete stuck EphemeralRunner objects manually (immediate relief):**
|
|
56
|
+
Identify stuck pods — they have been Running for longer than any expected job
|
|
57
|
+
duration and show "job was canceled" in their logs:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
kubectl get ephemerals -n arc-runners --sort-by=.metadata.creationTimestamp
|
|
61
|
+
kubectl logs <stuck-pod-name> -n arc-runners | grep "job was canceled"
|
|
62
|
+
kubectl delete ephemeralrunner <stuck-pod-name> -n arc-runners
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Option 2 — Add a watchdog sidecar or CronJob to detect and kill stuck runners:**
|
|
66
|
+
Run a periodic job that identifies EphemeralRunner pods that have been in Running
|
|
67
|
+
phase beyond `maxRunnerLifetime` and have no active child processes (no build
|
|
68
|
+
tools, compilers, or test runners as descendants):
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Detect hung runners: Running > 30 min with no CPU activity
|
|
72
|
+
kubectl get ephemerals -n arc-runners -o json | \
|
|
73
|
+
jq '.items[] | select(.status.phase=="Running") | .metadata.name'
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Option 3 — Configure autoscaling to replace stuck runners via scale-down:**
|
|
77
|
+
Set `maxRunners` to a value that triggers KEDA scale-down when load is low.
|
|
78
|
+
Scale-down deletes idle pods, including stuck ones. Ephemeral runners in the
|
|
79
|
+
"stuck/waiting" state appear idle to KEDA and will be cleaned up on the next
|
|
80
|
+
scale-down cycle.
|
|
81
|
+
|
|
82
|
+
**Option 4 — Use concurrency groups carefully to reduce cancellations:**
|
|
83
|
+
Each job cancellation risks creating a stuck runner. Reduce cancellation frequency
|
|
84
|
+
by scoping concurrency groups more narrowly (per-branch rather than per-repo):
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
concurrency:
|
|
88
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
89
|
+
cancel-in-progress: true
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Option 5 — Upgrade ARC and runner image:**
|
|
93
|
+
Track the upstream fix in ARC#4307. Check ARC release notes for a fix to the
|
|
94
|
+
runner's post-cancellation cleanup path. Ensure runner image is on the latest
|
|
95
|
+
minor version.
|
|
96
|
+
fix_code:
|
|
97
|
+
- language: yaml
|
|
98
|
+
label: 'Kubernetes CronJob watchdog to delete stuck ARC ephemeral runners'
|
|
99
|
+
code: |
|
|
100
|
+
apiVersion: batch/v1
|
|
101
|
+
kind: CronJob
|
|
102
|
+
metadata:
|
|
103
|
+
name: arc-runner-watchdog
|
|
104
|
+
namespace: arc-runners
|
|
105
|
+
spec:
|
|
106
|
+
schedule: "*/10 * * * *"
|
|
107
|
+
jobTemplate:
|
|
108
|
+
spec:
|
|
109
|
+
template:
|
|
110
|
+
spec:
|
|
111
|
+
serviceAccountName: arc-runner-watchdog-sa
|
|
112
|
+
containers:
|
|
113
|
+
- name: watchdog
|
|
114
|
+
image: bitnami/kubectl:latest
|
|
115
|
+
command:
|
|
116
|
+
- /bin/sh
|
|
117
|
+
- -c
|
|
118
|
+
- |
|
|
119
|
+
TIMEOUT_MINUTES=30
|
|
120
|
+
NOW=$(date +%s)
|
|
121
|
+
kubectl get ephemeralrunners -n arc-runners -o json | \
|
|
122
|
+
jq -r --argjson now "$NOW" --argjson timeout "$((TIMEOUT_MINUTES * 60))" \
|
|
123
|
+
'.items[] | select(.status.phase=="Running") |
|
|
124
|
+
select(($now - (.metadata.creationTimestamp | fromdateiso8601)) > $timeout) |
|
|
125
|
+
.metadata.name' | \
|
|
126
|
+
xargs -r -I{} kubectl delete ephemeralrunner {} -n arc-runners
|
|
127
|
+
restartPolicy: OnFailure
|
|
128
|
+
- language: yaml
|
|
129
|
+
label: 'Narrow concurrency groups to reduce job cancellations hitting ARC'
|
|
130
|
+
code: |
|
|
131
|
+
name: CI
|
|
132
|
+
on:
|
|
133
|
+
push:
|
|
134
|
+
branches: ['**']
|
|
135
|
+
pull_request:
|
|
136
|
+
concurrency:
|
|
137
|
+
# Scope to branch — only cancels duplicate runs on the same branch,
|
|
138
|
+
# not across all branches (reduces how often ARC runners get hit by cancellations)
|
|
139
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
140
|
+
cancel-in-progress: true
|
|
141
|
+
jobs:
|
|
142
|
+
build:
|
|
143
|
+
runs-on:
|
|
144
|
+
group: my-scale-set
|
|
145
|
+
steps:
|
|
146
|
+
- uses: actions/checkout@v4
|
|
147
|
+
- run: make build
|
|
148
|
+
prevention:
|
|
149
|
+
- "Monitor EphemeralRunner pod ages; any pod in Running phase beyond 2x your longest job duration is likely stuck"
|
|
150
|
+
- "Use narrow concurrency group scopes (per-branch) to minimize the frequency of job cancellations hitting ARC runners"
|
|
151
|
+
- "Configure KEDA scale-down (minRunners: 0 during off-hours) to naturally clear stuck runner pods"
|
|
152
|
+
- "Keep ARC controller and runner image on the latest stable release; the stuck-on-cancel bug has active upstream attention in ARC#4307"
|
|
153
|
+
- "For high-cancellation workflows (PR push loops), consider using GitHub-hosted runners which handle cancellation cleanup server-side"
|
|
154
|
+
docs:
|
|
155
|
+
- url: 'https://github.com/actions/actions-runner-controller/issues/4307'
|
|
156
|
+
label: 'ARC#4307: Ephemeral Runners get stuck when job is canceled or interrupted (11 reactions, open)'
|
|
157
|
+
- url: 'https://github.com/actions/actions-runner-controller/blob/master/docs/gha-runner-scale-set-controller/README.md'
|
|
158
|
+
label: 'ARC: GitHub Actions Runner Scale Set documentation'
|
|
159
|
+
- url: 'https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/troubleshooting-actions-runner-controller-errors'
|
|
160
|
+
label: 'GitHub Docs: Troubleshooting ARC errors'
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
id: silent-failures-120
|
|
2
|
+
title: 'github.event.schedule returns stale cron expression for 1-2 runs after updating workflow schedule'
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- schedule
|
|
7
|
+
- cron
|
|
8
|
+
- github.event.schedule
|
|
9
|
+
- stale-value
|
|
10
|
+
- routing
|
|
11
|
+
- trigger-payload
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'github\.event\.schedule.*[0-9\*\/\-\,]+'
|
|
14
|
+
flags: 'i'
|
|
15
|
+
- regex: 'Unknown schedule:\s+[0-9\*\/\-\, ]+'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'Evaluating String.*=>\s+''[0-9\*\/\-\, ]+'''
|
|
18
|
+
flags: 'i'
|
|
19
|
+
error_messages:
|
|
20
|
+
- "Error: Unknown schedule: 0 5 * * *"
|
|
21
|
+
- "##[debug]....=> '0 5 * * *'"
|
|
22
|
+
- "github.event.schedule evaluates to removed cron expression"
|
|
23
|
+
root_cause: |
|
|
24
|
+
GitHub's schedule dispatcher caches the cron expression strings associated with
|
|
25
|
+
each workflow internally. When a workflow's `on.schedule` block is updated (cron
|
|
26
|
+
expression changed or removed) and pushed to the default branch, the dispatcher's
|
|
27
|
+
internal state does not immediately sync with the new YAML. For 1-2 scheduled runs
|
|
28
|
+
after the change, the dispatcher fires the workflow with the OLD cron expression
|
|
29
|
+
in `github.event.schedule`, even though the executed YAML already contains the
|
|
30
|
+
updated cron string.
|
|
31
|
+
|
|
32
|
+
This means:
|
|
33
|
+
- A workflow with routing logic such as `if: github.event.schedule == '0 5 * * 1-5'`
|
|
34
|
+
silently skips those steps during the transition window
|
|
35
|
+
- A `case`/`switch`-style step that branches on `github.event.schedule` hits an
|
|
36
|
+
"unknown schedule" branch and logs a confusing error
|
|
37
|
+
- Multi-schedule workflows that use `github.event.schedule` to dispatch different jobs
|
|
38
|
+
produce wrong results for 1-2 runs post-update
|
|
39
|
+
|
|
40
|
+
The stale value typically clears within the next scheduled trigger cycle once the
|
|
41
|
+
dispatcher re-reads the updated workflow YAML from the default branch. The actual
|
|
42
|
+
workflow code that runs is the CURRENT version — only the event payload is stale.
|
|
43
|
+
|
|
44
|
+
Source: actions/runner#4241 (Feb 2026) — real-world failure confirmed in
|
|
45
|
+
ava-labs/firewood with stale '0 5 * * *' firing after update to '0 5 * * 1-5',
|
|
46
|
+
with debug logs showing the old value in the evaluator.
|
|
47
|
+
fix: |
|
|
48
|
+
**Option 1 — Use a fallback in cron-routing logic:**
|
|
49
|
+
When switching cron expressions, treat the transition period gracefully by adding
|
|
50
|
+
the OLD expression to your routing logic temporarily. After 2-3 scheduled cycles,
|
|
51
|
+
remove the old branch.
|
|
52
|
+
|
|
53
|
+
**Option 2 — Avoid routing on github.event.schedule entirely:**
|
|
54
|
+
Use separate workflow files for each schedule instead of branching inside one
|
|
55
|
+
workflow on `github.event.schedule`. Each schedule in its own file has an
|
|
56
|
+
independent dispatch state.
|
|
57
|
+
|
|
58
|
+
**Option 3 — Trigger a manual run after updating the schedule:**
|
|
59
|
+
After pushing the cron change, trigger the workflow via `workflow_dispatch` once.
|
|
60
|
+
This forces the dispatcher to re-evaluate the workflow file and typically clears
|
|
61
|
+
the stale state before the next real scheduled run.
|
|
62
|
+
|
|
63
|
+
**Option 4 — Accept and handle the stale run:**
|
|
64
|
+
Add a default/fallback case to your routing logic that gracefully handles an
|
|
65
|
+
unexpected `github.event.schedule` value rather than erroring:
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
- name: Route by schedule
|
|
69
|
+
run: |
|
|
70
|
+
case "${{ github.event.schedule }}" in
|
|
71
|
+
'0 5 * * 1-5') echo "Weekday run" ;;
|
|
72
|
+
'0 5 * * 6') echo "Saturday run" ;;
|
|
73
|
+
*) echo "Unknown schedule (possibly stale): ${{ github.event.schedule }}; skipping" ;;
|
|
74
|
+
esac
|
|
75
|
+
```
|
|
76
|
+
fix_code:
|
|
77
|
+
- language: yaml
|
|
78
|
+
label: 'Use separate workflows per schedule (avoids routing entirely)'
|
|
79
|
+
code: |
|
|
80
|
+
# weekday-job.yml
|
|
81
|
+
on:
|
|
82
|
+
schedule:
|
|
83
|
+
- cron: '0 5 * * 1-5'
|
|
84
|
+
jobs:
|
|
85
|
+
weekday:
|
|
86
|
+
runs-on: ubuntu-latest
|
|
87
|
+
steps:
|
|
88
|
+
- run: echo "Weekday build"
|
|
89
|
+
|
|
90
|
+
# saturday-job.yml
|
|
91
|
+
on:
|
|
92
|
+
schedule:
|
|
93
|
+
- cron: '0 5 * * 6'
|
|
94
|
+
jobs:
|
|
95
|
+
saturday:
|
|
96
|
+
runs-on: ubuntu-latest
|
|
97
|
+
steps:
|
|
98
|
+
- run: echo "Saturday build"
|
|
99
|
+
- language: yaml
|
|
100
|
+
label: 'Graceful fallback case when routing on github.event.schedule'
|
|
101
|
+
code: |
|
|
102
|
+
on:
|
|
103
|
+
schedule:
|
|
104
|
+
- cron: '0 5 * * 1-5'
|
|
105
|
+
- cron: '0 5 * * 6'
|
|
106
|
+
jobs:
|
|
107
|
+
dispatch:
|
|
108
|
+
runs-on: ubuntu-latest
|
|
109
|
+
steps:
|
|
110
|
+
- name: Route by schedule
|
|
111
|
+
run: |
|
|
112
|
+
case "${{ github.event.schedule }}" in
|
|
113
|
+
'0 5 * * 1-5') echo "Weekday build" ;;
|
|
114
|
+
'0 5 * * 6') echo "Saturday build" ;;
|
|
115
|
+
# Fallback handles stale values during transition window
|
|
116
|
+
*)
|
|
117
|
+
echo "Unrecognized schedule value: '${{ github.event.schedule }}'"
|
|
118
|
+
echo "This may be a stale value from before a recent schedule update."
|
|
119
|
+
echo "Skipping; next run should carry the updated expression."
|
|
120
|
+
;;
|
|
121
|
+
esac
|
|
122
|
+
prevention:
|
|
123
|
+
- "Never rely on github.event.schedule routing immediately after updating a cron expression; allow 2-3 cycles for dispatcher state to sync"
|
|
124
|
+
- "Prefer separate workflow files per schedule rather than branching on github.event.schedule inside a single workflow"
|
|
125
|
+
- "When routing on github.event.schedule is necessary, always include a default/fallback case that handles unexpected values gracefully"
|
|
126
|
+
- "Trigger a workflow_dispatch run after updating a cron expression to force dispatcher re-evaluation before the next scheduled cycle"
|
|
127
|
+
- "Add a debug step that logs github.event.schedule at the start of scheduled workflows to surface stale values immediately"
|
|
128
|
+
docs:
|
|
129
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule'
|
|
130
|
+
label: 'GitHub Docs: schedule event'
|
|
131
|
+
- url: 'https://github.com/actions/runner/issues/4241'
|
|
132
|
+
label: 'actions/runner#4241: Cron scheduled returns stale cron expression after updating workflow schedule triggers'
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
id: yaml-syntax-077
|
|
2
|
+
title: 'VS Code GitHub Actions extension / languageservices emits false "Context access might be invalid" warning for secrets.*, vars.*, needs.* in valid regular workflows'
|
|
3
|
+
category: yaml-syntax
|
|
4
|
+
severity: warning
|
|
5
|
+
tags:
|
|
6
|
+
- vscode
|
|
7
|
+
- languageservices
|
|
8
|
+
- false-positive
|
|
9
|
+
- secrets-context
|
|
10
|
+
- vars-context
|
|
11
|
+
- needs-context
|
|
12
|
+
- linting
|
|
13
|
+
- actionlint
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'Context access might be invalid:\s+secrets\.'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'Context access might be invalid:\s+vars\.'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
- regex: 'Context access might be invalid:\s+needs\.'
|
|
20
|
+
flags: 'i'
|
|
21
|
+
- regex: 'Unrecognized named-value:\s+''secrets'''
|
|
22
|
+
flags: 'i'
|
|
23
|
+
error_messages:
|
|
24
|
+
- "Context access might be invalid: secrets.MY_SECRET"
|
|
25
|
+
- "Context access might be invalid: vars.MY_VAR"
|
|
26
|
+
- "Context access might be invalid: needs.build.outputs.artifact-path"
|
|
27
|
+
- "Unrecognized named-value: 'secrets'"
|
|
28
|
+
root_cause: |
|
|
29
|
+
The VS Code GitHub Actions extension (github.vscode-github-actions) uses the
|
|
30
|
+
`@actions/languageservices` package for workflow linting and IntelliSense. The
|
|
31
|
+
language server performs static analysis without access to the repository's actual
|
|
32
|
+
secrets, variables, or environment configuration. It emits "Context access might
|
|
33
|
+
be invalid" warnings in several scenarios where the workflow is in fact correct:
|
|
34
|
+
|
|
35
|
+
1. **Repository-level secrets and variables**: The language server cannot query
|
|
36
|
+
the repository's secrets or variables store, so any `secrets.MY_SECRET` or
|
|
37
|
+
`vars.MY_VAR` reference triggers a warning. This affects every workflow that
|
|
38
|
+
uses custom secrets or variables — i.e., nearly all real-world workflows.
|
|
39
|
+
|
|
40
|
+
2. **Dynamic environment secrets**: When a workflow uses `environment: ${{ ... }}`
|
|
41
|
+
with an expression to select the environment at runtime, the language server
|
|
42
|
+
cannot statically resolve which environment's secrets are accessible. Even
|
|
43
|
+
validly scoped `secrets.*` references under dynamic environments are flagged.
|
|
44
|
+
|
|
45
|
+
3. **needs.* context across complex job dependency graphs**: The language server
|
|
46
|
+
sometimes flags `needs.X.outputs.Y` as invalid when job X is defined in the
|
|
47
|
+
same workflow but the graph is not trivially linear, or when `needs:` contains
|
|
48
|
+
a list of multiple dependencies.
|
|
49
|
+
|
|
50
|
+
**Why this is a false positive:**
|
|
51
|
+
The warnings are generated by the language server's static type system, which
|
|
52
|
+
requires compile-time knowledge of what secrets/variables exist. GitHub Actions
|
|
53
|
+
resolves these at runtime from the repository/organization secrets store — a
|
|
54
|
+
source the language server has no access to. The workflow runs correctly at
|
|
55
|
+
runtime; only the editor shows red squiggles.
|
|
56
|
+
|
|
57
|
+
This is an open known issue tracked in actions/languageservices#239 (assigned
|
|
58
|
+
to GitHub staff, reopened after partial fixes). Multiple VS Code extension issues
|
|
59
|
+
document the same root cause: vscode-github-actions#461, #452, #375, #533.
|
|
60
|
+
|
|
61
|
+
**Scope**: Affects anyone using the VS Code GitHub Actions extension
|
|
62
|
+
(github.vscode-github-actions) v0.x and v1.x with workflows using secrets,
|
|
63
|
+
variables, or multi-job dependency outputs. NOT an actionlint issue —
|
|
64
|
+
actionlint correctly handles these cases without false positives.
|
|
65
|
+
fix: |
|
|
66
|
+
**Option 1 — Suppress per-line (extension-specific comment):**
|
|
67
|
+
The language server respects `# ignore` comments to suppress specific warnings.
|
|
68
|
+
Add a comment on the line preceding the flagged expression:
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
env:
|
|
72
|
+
# ignore: context-access-might-be-invalid
|
|
73
|
+
MY_VAR: ${{ secrets.MY_SECRET }}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Note: This syntax is not standardized and may change with extension updates.
|
|
77
|
+
|
|
78
|
+
**Option 2 — Disable specific diagnostics in VS Code settings:**
|
|
79
|
+
In `.vscode/settings.json`, disable the diagnostic class:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"github-actions.workflows.pinned.refresh.enabled": true
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Option 3 — Ignore and trust runtime behavior:**
|
|
88
|
+
This is a false positive — the workflow will run correctly. If the warning is
|
|
89
|
+
distracting, the safest approach is to acknowledge it as a known extension
|
|
90
|
+
limitation and verify by running the workflow. GitHub Actions runtime correctly
|
|
91
|
+
resolves secrets, vars, and needs contexts.
|
|
92
|
+
|
|
93
|
+
**Option 4 — Use actionlint for CI-level linting (no false positives for secrets):**
|
|
94
|
+
`actionlint` does not flag `secrets.*` references as invalid (it correctly
|
|
95
|
+
treats them as opaque strings). For CI integration, prefer actionlint over
|
|
96
|
+
the VS Code extension's linter for automated checks.
|
|
97
|
+
fix_code:
|
|
98
|
+
- language: yaml
|
|
99
|
+
label: 'Workflow using secrets and vars — runs correctly despite VS Code warnings'
|
|
100
|
+
code: |
|
|
101
|
+
# This workflow is valid — VS Code warns but GitHub Actions runs it correctly.
|
|
102
|
+
# The "Context access might be invalid" warnings for secrets.* and vars.*
|
|
103
|
+
# are false positives from the languageservices static analyzer.
|
|
104
|
+
name: Deploy
|
|
105
|
+
on:
|
|
106
|
+
push:
|
|
107
|
+
branches: [main]
|
|
108
|
+
jobs:
|
|
109
|
+
deploy:
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
environment: production
|
|
112
|
+
steps:
|
|
113
|
+
- name: Use secret (VS Code may warn here — ignore it)
|
|
114
|
+
run: echo "Deploying..."
|
|
115
|
+
env:
|
|
116
|
+
API_KEY: ${{ secrets.API_KEY }} # false positive warning
|
|
117
|
+
BASE_URL: ${{ vars.DEPLOY_BASE_URL }} # false positive warning
|
|
118
|
+
- language: json
|
|
119
|
+
label: 'VS Code settings.json — disable noisy extension diagnostics'
|
|
120
|
+
code: |
|
|
121
|
+
{
|
|
122
|
+
"github-actions.workflows.pinned.refresh.enabled": true,
|
|
123
|
+
"github-actions.org-secrets.enabled": false
|
|
124
|
+
}
|
|
125
|
+
prevention:
|
|
126
|
+
- "Do not suppress workflow secrets or variables based on VS Code warnings — verify by actually running the workflow"
|
|
127
|
+
- "Use actionlint for CI-integrated linting; it handles secrets/vars correctly without false positives"
|
|
128
|
+
- "Keep the VS Code GitHub Actions extension updated; GitHub staff are actively working on reducing false positives in languageservices"
|
|
129
|
+
- "Check the languageservices GitHub repo (actions/languageservices) for known false positive issues before filing new bugs"
|
|
130
|
+
- "When sharing workflow snippets, note that VS Code warnings do not necessarily indicate real problems — always confirm against actual run output"
|
|
131
|
+
docs:
|
|
132
|
+
- url: 'https://github.com/actions/languageservices/issues/239'
|
|
133
|
+
label: 'actions/languageservices#239: Context access might be invalid is too aggressive (open, assigned)'
|
|
134
|
+
- url: 'https://github.com/github/vscode-github-actions/issues/461'
|
|
135
|
+
label: 'vscode-github-actions#461: Unrecognized Github Actions Secret Context (false positive)'
|
|
136
|
+
- url: 'https://github.com/github/vscode-github-actions/issues/452'
|
|
137
|
+
label: 'vscode-github-actions#452: False warning for actions/checkout: Context access might be invalid'
|
|
138
|
+
- url: 'https://github.com/github/vscode-github-actions/issues/375'
|
|
139
|
+
label: 'vscode-github-actions#375: false positive error on secrets context access in forks'
|
|
140
|
+
- url: 'https://github.com/rhysd/actionlint'
|
|
141
|
+
label: 'actionlint: alternative linter that handles secrets/vars without false positives'
|
package/package.json
CHANGED