@htekdev/actions-debugger 1.0.122 → 1.0.124

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.
@@ -0,0 +1,137 @@
1
+ id: caching-artifacts-072
2
+ title: 'actions/cache@v5 Restore Rate Limit (429) Silently Treated as Cache Miss'
3
+ category: caching-artifacts
4
+ severity: silent-failure
5
+ tags:
6
+ - cache
7
+ - rate-limit
8
+ - 429
9
+ - restore
10
+ - cache-miss
11
+ - silent-failure
12
+ - v5
13
+ - performance
14
+ patterns:
15
+ - regex: 'Warning: You''ve hit a rate limit, your rate limit will reset in \d+ seconds'
16
+ flags: 'i'
17
+ - regex: 'Failed to restore:.*GetCacheEntryDownloadURL.*Rate [Ll]imited'
18
+ flags: 'i'
19
+ - regex: 'Failed request: \(429\) Too Many Requests: rate limit exceeded'
20
+ flags: 'i'
21
+ error_messages:
22
+ - "Warning: You've hit a rate limit, your rate limit will reset in 18 seconds"
23
+ - "Warning: Failed to restore: Failed to GetCacheEntryDownloadURL: Rate Limited: Failed request: (429) Too Many Requests: rate limit exceeded"
24
+ - "Cache not found for input keys: goofy-b41b01ad3312fe1358359b7522c43860bfdad754166c7f1d385e51766e57b4c0"
25
+ root_cause: |
26
+ When the GitHub cache service rate-limits a cache restore lookup request with HTTP
27
+ 429 Too Many Requests, actions/cache@v5 does NOT retry the request. Instead, it
28
+ prints a warning and immediately treats the response as a cache miss, proceeding
29
+ with a full build from scratch.
30
+
31
+ The cache service includes a Retry-After header in the 429 response that tells the
32
+ client exactly how many seconds to wait before retrying (often ≤60 seconds). The
33
+ actions/cache implementation ignores this header entirely — no retry, no backoff,
34
+ no configurable behavior. The job simply never gets its cached dependencies.
35
+
36
+ This is a silent failure in the sense that:
37
+ 1. The job succeeds — it just rebuilds everything from scratch.
38
+ 2. No annotation or error is surfaced in the Actions UI. Only a Warning line in
39
+ the step log reveals what happened.
40
+ 3. The resulting build artifacts are correct, but the CI run takes 2–10x longer
41
+ than expected, masking the real cause.
42
+
43
+ Most commonly triggered in large matrix builds (20+ parallel jobs) where many jobs
44
+ simultaneously query the cache service and collectively exhaust the per-repo or
45
+ per-org cache API rate limit. Also reported on repos with heavy cross-job cache
46
+ sharing patterns.
47
+
48
+ Distinct from caching-artifacts-030 (cache-service-429-upload-ebadf-crash.yml):
49
+ that entry covers 429 during the cache UPLOAD phase which crashes with EBADF.
50
+ This entry covers 429 during the cache RESTORE/lookup phase which silently misses
51
+ — different operation, different error message, different impact, different fix path.
52
+
53
+ Source: actions/cache#1758 (May 2026, open); also reported in
54
+ oxidecomputer/hubris#2535 "CI fails intermittently on Windows while restoring cache"
55
+ (May 2026).
56
+ fix: |
57
+ There is no complete fix — this is an open upstream bug (actions/cache#1758).
58
+ The rate-limit retry path is not implemented in actions/cache. Workarounds:
59
+
60
+ Option 1 — Reduce cache API pressure by staggering matrix jobs:
61
+
62
+ strategy:
63
+ matrix: ...
64
+ max-parallel: 5 # Limit to 5 concurrent jobs instead of all at once
65
+
66
+ This reduces the burst of simultaneous restore calls and lowers the chance of
67
+ hitting the rate limit.
68
+
69
+ Option 2 — Add a retry wrapper using actions/cache's restore-keys cascade:
70
+
71
+ - uses: actions/cache@v5
72
+ id: cache
73
+ with:
74
+ key: ${{ runner.os }}-deps-${{ hashFiles('**/lockfile') }}
75
+ restore-keys: |
76
+ ${{ runner.os }}-deps-
77
+ - name: Warn on cache rate limit miss
78
+ if: steps.cache.outputs.cache-hit != 'true'
79
+ run: |
80
+ echo "::warning::Cache miss — may be rate limited. Check step log for 429."
81
+
82
+ Option 3 — Switch to a self-hosted cache backend to bypass GitHub's rate limits:
83
+
84
+ env:
85
+ ACTIONS_CACHE_URL: https://your-cache-backend.example.com/
86
+ ACTIONS_RUNTIME_TOKEN: ${{ secrets.CACHE_TOKEN }}
87
+
88
+ Option 4 — Accept it and add monitoring. If you frequently see the rate limit
89
+ warning, consider filing a support ticket to request a higher cache API rate limit
90
+ for your organization.
91
+ fix_code:
92
+ - language: yaml
93
+ label: 'Reduce parallelism to lower cache restore burst pressure'
94
+ code: |
95
+ jobs:
96
+ build:
97
+ strategy:
98
+ matrix:
99
+ target: [linux-x64, linux-arm64, windows-x64, macos-x64, macos-arm64]
100
+ max-parallel: 4 # Stagger jobs to reduce simultaneous cache restore calls
101
+ steps:
102
+ - uses: actions/cache@v5
103
+ with:
104
+ path: ~/.cargo/registry
105
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
106
+
107
+ - language: yaml
108
+ label: 'Add explicit warning step to surface rate limit cache misses clearly'
109
+ code: |
110
+ steps:
111
+ - uses: actions/cache@v5
112
+ id: cache-restore
113
+ with:
114
+ path: |
115
+ ~/.npm
116
+ node_modules
117
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
118
+ restore-keys: |
119
+ ${{ runner.os }}-node-
120
+
121
+ - name: Check for cache rate limit miss
122
+ if: steps.cache-restore.outputs.cache-hit != 'true'
123
+ run: |
124
+ echo "::warning::Cache miss detected — check step log for '429 Too Many Requests' to distinguish rate-limit miss from genuine cache absence."
125
+
126
+ prevention:
127
+ - 'Set max-parallel on matrix strategies to limit simultaneous cache restore API calls and avoid triggering the per-org/per-repo cache rate limit.'
128
+ - 'Monitor the cache restore step logs for the warning message "You''ve hit a rate limit" to distinguish rate-limit misses from genuine cache absences when diagnosing slow CI runs.'
129
+ - 'Consider using restore-keys fallback chains so that even a rate-limited primary key miss may still succeed with a partial restore from a broader key.'
130
+ - 'Report rate limit occurrences to GitHub Support with your org name to request a higher cache API rate limit if you encounter this regularly in large workflows.'
131
+ docs:
132
+ - url: 'https://github.com/actions/cache/issues/1758'
133
+ label: 'actions/cache#1758 — Handle rate limit (open, May 2026)'
134
+ - url: 'https://github.com/oxidecomputer/hubris/issues/2535'
135
+ label: 'oxidecomputer/hubris#2535 — CI fails intermittently on Windows while restoring cache (May 2026)'
136
+ - url: 'https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy'
137
+ label: 'GitHub Docs — Caching usage limits and eviction policy'
@@ -0,0 +1,83 @@
1
+ id: known-unsolved-070
2
+ title: 'ubuntu-24.04 image 20260513.135 breaks WireMock-Spring dynamic port binding in @ConfigurationProperties tests'
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - ubuntu
7
+ - ubuntu-24.04
8
+ - spring-boot
9
+ - wiremock
10
+ - configurationproperties
11
+ - regression
12
+ - java
13
+ - test
14
+ patterns:
15
+ - regex: 'foo\.bar\.service\.url=http://localhost:\d+'
16
+ flags: i
17
+ - regex: 'http://localhost:9008'
18
+ flags: i
19
+ - regex: '@ConfigurationProperties'
20
+ flags: i
21
+ - regex: 'wiremock-spring-boot'
22
+ flags: i
23
+ error_messages:
24
+ - 'foo.bar.service.url=http://localhost:<random>'
25
+ - 'The @ConfigurationProperties(prefix = "foo.bar.service") bean ends up bound to the static fallback URL from application-integration-test.yml (http://localhost:9008).'
26
+ - 'The HTTP client then hits localhost:9008 and the test times out.'
27
+ root_cause: |
28
+ Starting with Ubuntu 24.04 image `20260513.135`, some Spring Boot integration tests that rely on
29
+ `wiremock-spring-boot` dynamic port injection regress in GitHub Actions even though the same commit,
30
+ same JDK, and same test pass on `ubuntu-22.04` and on the older Ubuntu 24.04 image `20260413.86`.
31
+
32
+ The observed behavior is:
33
+ 1. WireMock starts and publishes a dynamic property such as `foo.bar.service.url=http://localhost:<port>`.
34
+ 2. The property is visible in logs before the Spring banner.
35
+ 3. The `@ConfigurationProperties` bean still binds to the static fallback value from YAML
36
+ (`http://localhost:9008`).
37
+ 4. The client calls the fallback URL and the test times out.
38
+
39
+ The exact platform-level trigger inside the updated runner image has not been isolated yet. The issue
40
+ is deterministic on the affected image family, reproducible across multiple repositories, and still open.
41
+ At the time of writing there is no confirmed runner-side fix or single root cause from GitHub.
42
+ fix: |
43
+ There is no confirmed upstream fix yet.
44
+
45
+ Current workarounds:
46
+ - pin the workflow to `ubuntu-22.04` while the Ubuntu 24.04 regression is investigated
47
+ - avoid test setups that rely on `@ConfigurationProperties` picking up a dynamically injected URL
48
+ - pass the WireMock URL through `@DynamicPropertySource`, a test-specific bean, or direct
49
+ `Environment` reads closer to the HTTP client wiring
50
+ fix_code:
51
+ - language: yaml
52
+ label: 'Pin the test job to Ubuntu 22.04 until the regression is fixed'
53
+ code: |
54
+ jobs:
55
+ integration-tests:
56
+ runs-on: ubuntu-22.04
57
+ steps:
58
+ - uses: actions/checkout@v4
59
+ - uses: actions/setup-java@v4
60
+ with:
61
+ distribution: temurin
62
+ java-version: '21'
63
+ - name: Run integration tests
64
+ run: ./mvnw test
65
+
66
+ - language: java
67
+ label: 'Inject the dynamic WireMock URL through DynamicPropertySource'
68
+ code: |
69
+ @DynamicPropertySource
70
+ static void registerWireMockProperties(DynamicPropertyRegistry registry) {
71
+ registry.add("foo.bar.service.url", wireMockServer::baseUrl);
72
+ }
73
+ prevention:
74
+ - 'Treat Ubuntu image rollouts as a possible source of Java integration-test regressions, even when your dependencies are unchanged.'
75
+ - 'Prefer explicit test-time property injection over fallback YAML values when the URL must come from a dynamically started mock server.'
76
+ - 'Keep a side-by-side `ubuntu-22.04` control job available when debugging new `ubuntu-latest` regressions.'
77
+ docs:
78
+ - url: 'https://github.com/actions/runner-images/issues/14136'
79
+ label: 'actions/runner-images#14136 — ubuntu-24.04 image 20260513.135 breaks WireMock-Spring dynamic ports'
80
+ - url: 'https://docs.spring.io/spring-framework/reference/testing/testcontext-framework/ctx-management/dynamic-property-sources.html'
81
+ label: 'Spring Docs — @DynamicPropertySource'
82
+ - url: 'https://github.com/wiremock/wiremock-spring-boot'
83
+ label: 'wiremock-spring-boot project'
@@ -0,0 +1,140 @@
1
+ id: runner-environment-222
2
+ title: 'Windows Self-Hosted Runner V2 Broker Listener Stops Polling After First Job Completion'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - self-hosted
7
+ - windows
8
+ - broker
9
+ - v2-flow
10
+ - listener
11
+ - polling
12
+ - idle
13
+ - 2.334.0
14
+ - BrokerMessageListener
15
+ patterns:
16
+ - regex: 'BrokerMessageListener.*Get messages has been cancelled using local token source\. Continue to get messages with new status\.'
17
+ flags: 'i'
18
+ - regex: 'BrokerMessageListener.*Received job status event\. JobState: Online'
19
+ flags: 'i'
20
+ error_messages:
21
+ - "[2026-05-21 14:48:13Z INFO BrokerMessageListener] Get messages has been cancelled using local token source. Continue to get messages with new status."
22
+ - "[INFO BrokerMessageListener] Received job status event. JobState: Online"
23
+ - "[INFO BrokerMessageListener] Session created."
24
+ root_cause: |
25
+ On Windows self-hosted runners using the V2 broker protocol (useV2Flow: true,
26
+ serverUrlV2: broker.actions.githubusercontent.com), a race condition in the
27
+ BrokerMessageListener causes the runner to permanently stop polling the broker
28
+ after the first job completes.
29
+
30
+ The sequence that triggers the hang:
31
+ 1. Runner starts, creates a broker session, and begins polling for messages.
32
+ 2. First job arrives → BrokerMessageListener logs "JobState: Busy".
33
+ 3. Job finishes → BrokerMessageListener logs "JobState: Online".
34
+ 4. The Online state transition triggers a cancellation of the current polling
35
+ loop via a local token source ("Get messages has been cancelled using
36
+ local token source. Continue to get messages with new status.").
37
+ 5. The listener is supposed to create a new polling loop with fresh state, but
38
+ due to a bug in the V2 flow state machine, the new polling loop is never
39
+ started. No further GET /message requests are ever issued.
40
+
41
+ The runner process stays alive. OAuth token refreshes continue on schedule (so
42
+ credentials are not the problem). The runner shows as "Idle" in the GitHub UI.
43
+ However, it will never pick up another job until the service is manually restarted.
44
+
45
+ The bug was introduced in or around v2.334.0 on Windows. It does not affect:
46
+ - Linux runners (different socket layer — see broker-server-socket-exception-nat-timeout-linux.yml)
47
+ - macOS runners (see macos-self-hosted-listener-aad-ghost-busy-stall.yml for a
48
+ separate macOS stall pattern)
49
+ - V1 flow runners (useV2Flow: false)
50
+ - GitHub-hosted runners (not affected by self-hosted listener bugs)
51
+
52
+ Source: actions/runner#4444 (May 2026, open). Reported on Windows Server 2022
53
+ x64, v2.334.0, V2 flow. Three reproducible occurrences in 22 hours on a
54
+ previously stable 6+ day continuous runner.
55
+ fix: |
56
+ Immediate fix — Restart the runner service to recover:
57
+
58
+ Restart-Service actions.runner.*
59
+
60
+ Or via the runner management interface:
61
+ 1. Go to repo/org Settings → Actions → Runners
62
+ 2. Force-remove the stale runner registration
63
+ 3. Re-register and restart
64
+
65
+ Structural workarounds:
66
+
67
+ Option 1 — Switch to ephemeral runners (recommended for most use cases):
68
+ Ephemeral runners register once, run one job, and exit cleanly. No stale state.
69
+
70
+ ./config.sh --url https://github.com/ORG/REPO --token TOKEN --ephemeral
71
+ ./run.sh
72
+
73
+ Or with Actions Runner Controller (ARC):
74
+ autoscaling.runnerScaleSetListener.minRunners: 1
75
+
76
+ Option 2 — Revert to V1 broker flow if ephemeral is not an option:
77
+ The V1 flow (long-polling, non-broker) does not exhibit this specific hang.
78
+ Edit the .runner config file and set useV2Flow: false, then restart the service.
79
+ Note: V1 is deprecated and will eventually be removed.
80
+
81
+ Option 3 — Add an automatic service recovery watchdog:
82
+
83
+ # Windows Task Scheduler: check every 5 minutes if runner has been Idle >20min
84
+ # and restart the service if it's stuck
85
+ $runner = Get-Service "actions.runner.*"
86
+ if ($runner.Status -eq "Running") {
87
+ # Check last job timestamp via API; if >20min and jobs queued, restart
88
+ Restart-Service "actions.runner.*"
89
+ }
90
+
91
+ Option 4 — Pin to a known-good runner version:
92
+ If v2.334.0+ reliably triggers this, pin the runner to v2.333.x by editing
93
+ the .runner config and disabling auto-update. Note: outdated versions
94
+ eventually stop being able to receive messages.
95
+ fix_code:
96
+ - language: yaml
97
+ label: 'Use ephemeral runners to avoid stale listener state entirely'
98
+ code: |
99
+ # In your workflow:
100
+ jobs:
101
+ build:
102
+ runs-on: [self-hosted, windows-x64] # Labels for your runner pool
103
+
104
+ # Register runners as ephemeral:
105
+ # ./config.cmd --url https://github.com/ORG/REPO --token TOKEN --ephemeral
106
+ # Each runner exits after completing one job; a process manager (NSSM, task
107
+ # scheduler, or ARC) restarts it to accept the next job.
108
+
109
+ - language: yaml
110
+ label: 'Add watchdog step to detect stale listener symptom (queue depth check)'
111
+ code: |
112
+ # Optional diagnostic: surface "no runners picked up job for >N minutes" via API
113
+ # Run this in a separate monitoring workflow:
114
+ jobs:
115
+ watchdog:
116
+ runs-on: ubuntu-latest
117
+ steps:
118
+ - name: Check for stuck self-hosted Windows runners
119
+ env:
120
+ GH_TOKEN: ${{ secrets.RUNNER_ADMIN_PAT }}
121
+ run: |
122
+ # List queued jobs older than 10 minutes that are assigned to self-hosted
123
+ gh api repos/${{ github.repository }}/actions/runs \
124
+ --jq '.workflow_runs[] | select(.status=="queued") | .id' \
125
+ | while read run_id; do
126
+ echo "Queued run: $run_id"
127
+ done
128
+
129
+ prevention:
130
+ - 'Use ephemeral self-hosted runners — they register, run one job, and exit. No stale listener state can accumulate.'
131
+ - 'If using long-lived runners on Windows with V2 broker flow, add monitoring to detect runners stuck in the Idle state with queued jobs.'
132
+ - 'Set up automatic service recovery for the runner service on Windows (e.g., via Windows Service recovery actions: restart after 1st failure).'
133
+ - 'Monitor actions/runner release notes for a fix to the V2 listener polling regression introduced around v2.334.0.'
134
+ docs:
135
+ - url: 'https://github.com/actions/runner/issues/4444'
136
+ label: 'actions/runner#4444 — Listener stops polling broker after first job''s Busy→Online transition (2.334.0, Windows, V2 flow)'
137
+ - url: 'https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/running-scripts-before-or-after-a-job'
138
+ label: 'GitHub Docs — Self-hosted runner configuration'
139
+ - url: 'https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/autoscaling-with-self-hosted-runners'
140
+ label: 'GitHub Docs — Autoscaling with self-hosted runners (ephemeral runner pattern)'
@@ -0,0 +1,149 @@
1
+ id: runner-environment-223
2
+ title: 'macOS-15 Arm64 brew update Fails with Stale lockf Lock When Run Twice'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - macos
7
+ - homebrew
8
+ - brew-update
9
+ - lockf
10
+ - arm64
11
+ - macos-15
12
+ - regression
13
+ - concurrent
14
+ patterns:
15
+ - regex: 'lockf: 200: already locked'
16
+ flags: 'i'
17
+ - regex: 'Error: Another `brew update` process is already running\.'
18
+ flags: 'i'
19
+ - regex: 'lockf:.*already locked\s*\nError: Another.*brew update.*process is already running'
20
+ flags: 'im'
21
+ error_messages:
22
+ - "lockf: 200: already locked"
23
+ - "Error: Another `brew update` process is already running."
24
+ - "Please wait for it to finish or terminate it to continue."
25
+ - "Error: Process completed with exit code 1."
26
+ root_cause: |
27
+ On macOS-15 Arm64 GitHub Actions hosted runners starting with image version
28
+ 20260422.526 (released ~April 22, 2026), running `brew update` more than once
29
+ within the same workflow — or across two steps that both call `brew update` —
30
+ fails on the second invocation with a stale lockf lock error.
31
+
32
+ Homebrew uses a lockfile at `/opt/homebrew/Library/Taps/homebrew/homebrew-core/.git/index.lock`
33
+ (or a similar path) to prevent concurrent updates. In the affected image versions,
34
+ the first `brew update` completes successfully but leaves the lock file in a
35
+ state that subsequent `brew update` calls cannot acquire. The `lockf` system
36
+ call returns errno 200 (EDEADLK on macOS), which Homebrew surfaces as
37
+ "Another brew update process is already running."
38
+
39
+ This is a regression — the same workflow step pattern worked correctly on image
40
+ version 20260415.520 and earlier.
41
+
42
+ Common trigger patterns:
43
+ 1. Explicit double-update in a single step: `brew update && brew update`
44
+ 2. Two separate steps that each call `brew update` before installing different tools
45
+ 3. Parallel jobs on the same runner image that both run `brew update` (less common
46
+ since each hosted runner job gets a fresh VM, but affects matrix jobs in the
47
+ same workflow when they share a Homebrew setup step via the action cache)
48
+ 4. A step script that calls `brew update` internally AND the user also calls it
49
+
50
+ Note: This affects macOS-15 Arm64 specifically. macOS-14, macOS-26, and x86_64
51
+ variants were NOT marked as affected in the original bug report (runner-images#13965).
52
+
53
+ Source: actions/runner-images#13965 (April 2026, open, under investigation by
54
+ GitHub runner-images team). Reported with reproducible case from the
55
+ mullvad/mullvadvpn-app CI pipeline.
56
+ fix: |
57
+ Option 1 — Run brew update only once per job (preferred):
58
+
59
+ Consolidate all your brew installations into a single step and call brew update
60
+ exactly once before them:
61
+
62
+ - name: Install dependencies
63
+ run: |
64
+ brew update
65
+ brew install cmake ninja pkg-config
66
+
67
+ Option 2 — Use HOMEBREW_NO_AUTO_UPDATE=1 on steps that don't need fresh formulae:
68
+
69
+ If you only need brew update for specific steps, set the env var on all other
70
+ brew-using steps to prevent automatic update attempts:
71
+
72
+ - name: Install specific tool
73
+ env:
74
+ HOMEBREW_NO_AUTO_UPDATE: '1'
75
+ run: brew install your-tool # Skips the implicit brew update
76
+
77
+ Option 3 — Guard the second brew update with a lock check:
78
+
79
+ - name: Safe brew update
80
+ run: |
81
+ flock -xn /opt/homebrew/Library/Taps/homebrew/homebrew-core/.git/index.lock \
82
+ brew update || echo "::warning::brew update skipped (lock already held)"
83
+
84
+ Option 4 — Use brew upgrade instead of repeated brew update:
85
+ If you need the latest formula versions, run brew update once and then
86
+ use brew upgrade to update installed packages:
87
+
88
+ - name: Update and upgrade Homebrew
89
+ run: |
90
+ brew update # Run exactly once
91
+ brew upgrade # Upgrades installed formulae to latest
92
+
93
+ Option 5 — Check for the regression in your image version and pin:
94
+ If you need to pin to a known-good image version while the fix is pending,
95
+ see GitHub's runner-images documentation for image version pinning options
96
+ (note: pinning is not officially supported for GitHub-hosted standard runners).
97
+ fix_code:
98
+ - language: yaml
99
+ label: 'Broken — two brew update calls in same workflow (second fails on affected image)'
100
+ code: |
101
+ # This fails on macOS-15 Arm64 image 20260422.526+ with lockf: 200: already locked:
102
+ steps:
103
+ - name: Install build tools
104
+ run: |
105
+ brew update
106
+ brew install cmake ninja
107
+
108
+ - name: Install test tools
109
+ run: |
110
+ brew update # FAILS: Another brew update process is already running
111
+ brew install lcov
112
+
113
+ - language: yaml
114
+ label: 'Fixed — single brew update before consolidated installs'
115
+ code: |
116
+ # Consolidate into one brew update call at the start:
117
+ steps:
118
+ - name: Install all Homebrew tools
119
+ run: |
120
+ brew update # Only call once per job
121
+ brew install cmake ninja lcov
122
+
123
+ - language: yaml
124
+ label: 'Fixed — use HOMEBREW_NO_AUTO_UPDATE=1 on subsequent brew steps'
125
+ code: |
126
+ # Or prevent auto-update on steps after the first:
127
+ steps:
128
+ - name: Install build tools
129
+ run: |
130
+ brew update
131
+ brew install cmake ninja
132
+
133
+ - name: Install test tools (no re-update needed)
134
+ env:
135
+ HOMEBREW_NO_AUTO_UPDATE: '1'
136
+ run: brew install lcov # Uses existing formula cache; no brew update call
137
+
138
+ prevention:
139
+ - 'Call brew update at most once per job. Consolidate all Homebrew installations into a single step with one brew update at the top.'
140
+ - 'Set HOMEBREW_NO_AUTO_UPDATE=1 as a job-level env var and call brew update explicitly only in the one step that needs it.'
141
+ - 'Pin to macOS-14 (macos-14-xlarge) or use macOS-26 (which has different Homebrew behavior) if the regression is blocking critical workflows while runner-images#13965 is open.'
142
+ - 'Check your CI logs for the "lockf: 200: already locked" error if macOS-15 Arm64 workflows started failing around late April 2026 — this regression is the likely cause.'
143
+ docs:
144
+ - url: 'https://github.com/actions/runner-images/issues/13965'
145
+ label: 'actions/runner-images#13965 — Running brew update twice in one workflow breaks (open, April 2026)'
146
+ - url: 'https://docs.brew.sh/Manpage#environment'
147
+ label: 'Homebrew docs — HOMEBREW_NO_AUTO_UPDATE environment variable'
148
+ - url: 'https://github.com/mullvad/mullvadvpn-app/actions/runs/24890005834'
149
+ label: 'mullvad/mullvadvpn-app — Example failing run (regression confirmed between image 20260415 and 20260422)'
@@ -0,0 +1,74 @@
1
+ id: runner-environment-224
2
+ title: 'windows-2025-vs2026 UWP builds with PlatformToolset v143 fail with MSB8020'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - windows
7
+ - uwp
8
+ - msvc
9
+ - vs2026
10
+ - v143
11
+ - v145
12
+ - msbuild
13
+ - migration
14
+ patterns:
15
+ - regex: 'MSB8020: The build tools for ''v143'' application Type UWP \(Platform Toolset = ''Visual Studio 2022''\) cannot be found'
16
+ flags: i
17
+ - regex: '<PlatformToolset>v143</PlatformToolset>'
18
+ flags: i
19
+ - regex: 'windows-2025-vs2026'
20
+ flags: i
21
+ error_messages:
22
+ - 'MSBUILD : error MSB8020: The build tools for ''v143'' application Type UWP (Platform Toolset = ''Visual Studio 2022'') cannot be found.'
23
+ - 'The same project builds cleanly on windows-2025 (VS 2022) because v143 is the native toolset there.'
24
+ root_cause: |
25
+ The `windows-2025-vs2026` image is a Visual Studio 2026 image. It ships the VS 2026
26
+ native MSVC toolset (`v145`), but it does NOT include the legacy VS 2022 UWP toolset
27
+ overlay for `PlatformToolset=v143`.
28
+
29
+ Legacy UWP C++ projects often keep `<PlatformToolset>v143</PlatformToolset>` in the
30
+ `.vcxproj` file. That works on `windows-2025` (VS 2022), but when the same workflow is
31
+ moved to `windows-2025-vs2026` — or when `windows-latest` rolls onto the VS 2026 image —
32
+ MSBuild fails at `PrepareForBuild` with MSB8020 before compilation starts.
33
+
34
+ Issue #14101 was later clarified by the reporter: the break is real, but the root cause is
35
+ not a partially missing component. The image is behaving as a VS 2026-only environment, and
36
+ the workflow is still targeting an older UWP toolset that is no longer present there.
37
+ fix: |
38
+ Option 1 — Migrate the project to `PlatformToolset=v145` (recommended on VS 2026 images).
39
+
40
+ Option 2 — If the project must stay on `v143`, pin the workflow to a VS 2022 image such as
41
+ `windows-2025` instead of `windows-2025-vs2026` or `windows-latest`.
42
+
43
+ Option 3 — Isolate legacy UWP builds in a dedicated workflow that stays on VS 2022 while the
44
+ rest of the repository migrates to VS 2026.
45
+ fix_code:
46
+ - language: xml
47
+ label: 'Migrate the project file to the VS 2026 toolset'
48
+ code: |
49
+ <PropertyGroup Label="Configuration">
50
+ <ConfigurationType>StaticLibrary</ConfigurationType>
51
+ <PlatformToolset>v145</PlatformToolset>
52
+ </PropertyGroup>
53
+
54
+ - language: yaml
55
+ label: 'Keep legacy UWP builds on the VS 2022 image'
56
+ code: |
57
+ jobs:
58
+ build-uwp:
59
+ runs-on: windows-2025
60
+ steps:
61
+ - uses: actions/checkout@v4
62
+ - name: Build legacy UWP project
63
+ run: msbuild MyApp.sln /p:Configuration=Release /p:Platform=x64
64
+ prevention:
65
+ - 'Audit Windows workflows for `<PlatformToolset>v143</PlatformToolset>` before moving them to `windows-2025-vs2026` or `windows-latest`.'
66
+ - 'Treat Visual Studio image migrations as toolchain migrations, not just path changes.'
67
+ - 'Pin `runs-on` explicitly for legacy UWP projects until the toolset migration is complete.'
68
+ docs:
69
+ - url: 'https://github.com/actions/runner-images/issues/14101'
70
+ label: 'actions/runner-images#14101 — windows-2025-vs2026 UWP project fails with MSB8020 on v143'
71
+ - url: 'https://github.com/actions/runner-images/issues/14017'
72
+ label: 'actions/runner-images#14017 — Windows 2025 / VS 2026 rollout announcement'
73
+ - url: 'https://learn.microsoft.com/en-us/cpp/build/reference/msbuild-visual-cpp-overview'
74
+ label: 'Microsoft Docs — MSBuild and Visual C++ toolsets'
@@ -0,0 +1,85 @@
1
+ id: runner-environment-225
2
+ title: 'macOS-26 arm runners can miss the iOS 26.1 simulator runtime needed by Xcode 26.1.1'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - macos
7
+ - macos-26
8
+ - arm64
9
+ - xcode
10
+ - simulator
11
+ - ios
12
+ - xcodebuild
13
+ - runner-image
14
+ patterns:
15
+ - regex: 'Unable to find a destination matching the provided destination specifier:'
16
+ flags: i
17
+ - regex: 'iOS 26\.1 is not installed\. Please download and install the platform from Xcode > Settings > Components\.'
18
+ flags: i
19
+ - regex: 'Exit status: 70'
20
+ flags: i
21
+ error_messages:
22
+ - 'xcodebuild: error: Unable to find a destination matching the provided destination specifier:'
23
+ - '{ platform:iOS, id:dvtdevice-DVTiPhonePlaceholder-iphoneos:placeholder, name:Any iOS Device, error:iOS 26.1 is not installed. Please download and install the platform from Xcode > Settings > Components. }'
24
+ - 'Exit status: 70'
25
+ root_cause: |
26
+ The macOS 26 arm64 image version `20260520.0098.1` can expose Xcode 26.1.1 without shipping
27
+ the matching iOS 26.1 simulator/runtime components that Apple tooling expects for that Xcode.
28
+
29
+ Workflows that switch to Xcode 26.1.1 and build for iOS hit an immediate xcodebuild destination
30
+ failure because the placeholder device reports `iOS 26.1 is not installed`. The problem is on the
31
+ runner image, not in the project: the requested platform runtime is simply absent from the hosted
32
+ image at execution time.
33
+
34
+ This differs from the later macOS 26 default-Xcode migration entry: here the failure is a missing
35
+ runtime on the selected Xcode/image combination, not a project that needs to unpin from an older
36
+ Xcode.
37
+ fix: |
38
+ Option 1 — Select an Xcode version whose simulator/runtime set is actually present on the image.
39
+
40
+ Option 2 — Use `OS=latest` or another available simulator destination after checking the installed
41
+ runtimes with `xcrun simctl list runtimes`.
42
+
43
+ Option 3 — Wait for the next runner-image rollout that includes the missing iOS 26.1 runtime if the
44
+ project explicitly requires Xcode 26.1.1.
45
+ fix_code:
46
+ - language: yaml
47
+ label: 'Probe runtimes before building and use an installed simulator version'
48
+ code: |
49
+ jobs:
50
+ ios-build:
51
+ runs-on: macos-26-arm64
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+ - name: Show installed runtimes
55
+ run: xcrun simctl list runtimes
56
+ - name: Build with an installed simulator runtime
57
+ run: |
58
+ xcodebuild build \
59
+ -scheme MyApp \
60
+ -destination 'platform=iOS Simulator,OS=latest,name=iPhone 17 Pro'
61
+
62
+ - language: yaml
63
+ label: 'Pin to a different Xcode already supported by the image'
64
+ code: |
65
+ jobs:
66
+ ios-build:
67
+ runs-on: macos-26-arm64
68
+ steps:
69
+ - uses: actions/checkout@v4
70
+ - uses: maxim-lobanov/setup-xcode@v1
71
+ with:
72
+ xcode-version: '26.4.1'
73
+ - name: Build
74
+ run: xcodebuild build -scheme MyApp -destination 'generic/platform=iOS'
75
+ prevention:
76
+ - 'Always dump `xcrun simctl list runtimes` in CI when adopting a new Xcode/image combination.'
77
+ - 'Prefer `OS=latest` unless your workflow truly requires one exact simulator runtime.'
78
+ - 'Pin both the runner label and Xcode version during major Apple platform transitions.'
79
+ docs:
80
+ - url: 'https://github.com/actions/runner-images/issues/14146'
81
+ label: 'actions/runner-images#14146 — macos-26 arm runner missing iOS simulator 26.1'
82
+ - url: 'https://developer.apple.com/documentation/xcode/installing-additional-simulator-runtimes'
83
+ label: 'Apple Docs — Installing additional simulator runtimes'
84
+ - url: 'https://github.com/maxim-lobanov/setup-xcode'
85
+ label: 'maxim-lobanov/setup-xcode action'
@@ -0,0 +1,91 @@
1
+ id: runner-environment-226
2
+ title: '.NET MAUI iOS publish on macOS-26 can fail because Xcode 26.5 lacks the simulator runtime actool expects'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - macos
7
+ - macos-26
8
+ - maui
9
+ - dotnet
10
+ - ios
11
+ - xcode
12
+ - actool
13
+ - runner-image
14
+ patterns:
15
+ - regex: 'No simulator runtime version from \["23B86", "23C54", "23E254a"\] available to use with iphonesimulator SDK version 23F5054d'
16
+ flags: i
17
+ - regex: 'xcrun: error: unable to find utility "actool"'
18
+ flags: i
19
+ - regex: 'This version of \.NET for iOS \(26\.5\.9001\) requires Xcode 26\.5'
20
+ flags: i
21
+ error_messages:
22
+ - 'No simulator runtime version from ["23B86", "23C54", "23E254a"] available to use with iphonesimulator SDK version 23F5054d'
23
+ - 'xcrun: error: unable to find utility "actool"'
24
+ - 'This version of .NET for iOS (26.5.9001) requires Xcode 26.5'
25
+ root_cause: |
26
+ On the early macOS 26 hosted image rollout, users building .NET MAUI iOS apps with
27
+ `Microsoft.iOS.Sdk` 26.5.9001 were forced into an impossible toolchain combination.
28
+
29
+ `Microsoft.iOS.Sdk` 26.5.9001 requires Xcode 26.5, so downgrading to Xcode 26.4.1 is not a valid
30
+ long-term fix. But the Xcode 26.5 paths that were present on the image had two different failure
31
+ modes:
32
+ - selecting `/Applications/Xcode_26.5.app` or `/Applications/Xcode_26.5.0.app` could not resolve
33
+ `actool`
34
+ - selecting `/Applications/Xcode_26.5_beta_2.app` resolved `actool`, but the required simulator
35
+ runtime for SDK `23F5054d` was not installed
36
+
37
+ GitHub later confirmed that the Xcode 26.5 runtime would arrive on the next image update. Until
38
+ that rollout completed, the hosted image simply did not provide a fully working Xcode 26.5 + MAUI
39
+ iOS 26.5.9001 combination.
40
+ fix: |
41
+ There is no complete workflow-only fix when the hosted image is missing the runtime that Xcode and
42
+ the .NET iOS workload require.
43
+
44
+ Current options:
45
+ - wait for the next runner-image rollout that includes the Xcode 26.5 runtime
46
+ - temporarily downgrade the .NET iOS workload to a version compatible with Xcode 26.4.1
47
+ - add a preflight check so the job fails fast with a clear message instead of burning minutes in publish
48
+ fix_code:
49
+ - language: yaml
50
+ label: 'Fail fast if the required Xcode 26.5 simulator runtime is absent'
51
+ code: |
52
+ jobs:
53
+ publish-ios:
54
+ runs-on: macos-26
55
+ steps:
56
+ - uses: actions/checkout@v4
57
+ - name: Check installed runtimes
58
+ run: |
59
+ xcrun simctl list runtimes
60
+ xcodebuild -version
61
+ - name: Guard against missing Xcode 26.5 runtime
62
+ run: |
63
+ xcrun simctl list runtimes | grep '23F5054d' || {
64
+ echo 'Required Xcode 26.5 simulator runtime is missing on this image.'
65
+ exit 1
66
+ }
67
+
68
+ - language: yaml
69
+ label: 'Pin Xcode 26.4.1 while using a matching older iOS workload'
70
+ code: |
71
+ jobs:
72
+ publish-ios:
73
+ runs-on: macos-26
74
+ steps:
75
+ - uses: actions/checkout@v4
76
+ - uses: maxim-lobanov/setup-xcode@v1
77
+ with:
78
+ xcode-version: '26.4.1'
79
+ - name: Publish with a workload version that matches Xcode 26.4.1
80
+ run: dotnet publish -f net9.0-ios -c Release -r ios-arm64
81
+ prevention:
82
+ - 'Check `xcrun simctl list runtimes` whenever you adopt a new Xcode or .NET iOS workload on hosted macOS images.'
83
+ - 'Pin both Xcode and the .NET iOS workload version together during Apple platform transitions.'
84
+ - 'Add a fast runtime preflight before long `dotnet publish` steps so broken image rollouts fail immediately.'
85
+ docs:
86
+ - url: 'https://github.com/actions/runner-images/issues/14128'
87
+ label: 'actions/runner-images#14128 — macOS-26 hosted image missing simulator runtime required by Xcode 26.5'
88
+ - url: 'https://github.com/actions/runner-images/pull/14114'
89
+ label: 'runner-images pull request referenced in the fix confirmation'
90
+ - url: 'https://learn.microsoft.com/en-us/dotnet/maui/ios/deployment/'
91
+ label: 'Microsoft Docs — .NET MAUI iOS deployment'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.122",
3
+ "version": "1.0.124",
4
4
  "description": "65+ real GitHub Actions errors, queryable by agents. CLI + MCP server + Copilot skills + error database.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",