Workflow run
https://github.com/OpenStaticFish/ZigCraft/actions/runs/29183938238
Symptom
The visual-test workflow fails at step 8 ("Ensure visual-test label exists") and never reaches step 10 ("Run menu screenshot capture"). As a result, no screenshot.png is produced and no build-output.log is written — every downstream step is skipped. This is the same failure observed on the previous scheduled run (#17, https://github.com/OpenStaticFish/ZigCraft/actions/runs/29143688205) and re-occurred on the run that produced this issue (#18).
Relevant error output
From 0_visual-test.txt for run #17 (the failure is byte-for-byte identical on run #18):
2026-07-11T06:59:02.2188083Z if ! gh label list --json name --jq '.[].name' | grep -q '^run-visual-test$'; then
2026-07-11T06:59:02.2188445Z gh label create "run-visual-test" \
2026-07-11T06:59:02.2188798Z --description "Run deterministic visual regression workflow on a PR" \
2026-07-11T06:59:02.2189127Z --color "E06C75"
2026-07-11T06:59:02.2189340Z fi
…
2026-07-11T06:59:03.0186758Z label with name "run-visual-test" already exists; use `--force` to update its color and description
2026-07-11T06:59:03.0197803Z ##[error]Process completed with exit code 1.
Job step status for run #18 (current run):
| # |
Step |
Status |
| 8 |
Ensure visual-test label exists |
failure |
| 9 |
Setup Lavapipe Vulkan |
skipped |
| 10 |
Run menu screenshot capture |
skipped |
| 11 |
Check screenshot exists |
success (exists=false) |
| 12-17 |
downstream steps |
skipped |
| 18 |
Run opencode failure diagnosis |
in_progress |
Root cause
The pre-flight existence check in .github/workflows/visual-test.yml:55-68 is buggy:
- name: Ensure visual-test label exists
run: |
if ! gh label list --json name --jq '.[].name' | grep -q '^visual-test$'; then
gh label create "visual-test" \
--description "Issues from automated visual regression tests" \
--color "E06C75"
fi
if ! gh label list --json name --jq '.[].name' | grep -q '^run-visual-test$'; then
gh label create "run-visual-test" \
--description "Run deterministic visual regression workflow on a PR" \
--color "E06C75"
fi
gh label list (without --paginate or a higher --limit) returns only the first 30 labels, sorted alphabetically. This repo now has 41 labels. Both target labels fall outside the first page when sorted alphabetically:
$ gh label list --repo OpenStaticFish/ZigCraft --json name --jq '.[].name' | nl | tail -15
16 world
17 shaders
18 hotfix
19 automated-audit
20 automated-test
21 visual-test # <-- last label that IS returned by default
22 batch-1
23 batch-2
…
30 perf/gpu-compute
# run-visual-test, perf/bandwidth, … are not in this output
$ gh label list --repo OpenStaticFish/ZigCraft --json name --jq '.[].name' | wc -l
30
Because run-visual-test is past position 30 in the default page, grep -q '^run-visual-test$' exits 1, the if ! inverts that to 0 (true), and gh label create "run-visual-test" runs — and gh label create errors out because the label already exists:
label with name "run-visual-test" already exists; use `--force` to update its color and description
visual-test happens to land at position 21, inside the default page, so that check is currently lucky. The bug is the same for both checks — only run-visual-test is failing today because it sorts past the 30-item cutoff. As more labels are added to the repo, visual-test will also drop off the first page and start failing.
The check has been broken since the repo crossed 30 labels. It never had any effect on the visual-test job — it has always aborted before step 10 even ran — which is why no build-output.log exists in the diagnosis workspace for runs #17 and #18: the build was never invoked.
(Note: issue #913 from run #17 was filed by the same diagnosis flow but misattributed the failure to "PPM screenshot capture is unsupported" because the build log was missing. The actual failure on that run — and on run #18 — is the label-creation error above. #913 should be closed once this issue is fixed.)
File / function where the failure originates
- File:
.github/workflows/visual-test.yml
- Step:
Ensure visual-test label exists (lines 55-68)
- Failing command:
gh label create "run-visual-test" invoked on line 63, reached because the guard on line 62 returns the wrong answer when paginated.
Suggested fix
Either fetch all labels so the guard sees the full list, or make the create itself idempotent. Either of the following edits to .github/workflows/visual-test.yml resolves the failure:
Option A — paginate the list query (smallest change)
- name: Ensure visual-test label exists
run: |
if ! gh label list --paginate --json name --jq '.[].name' | grep -q '^visual-test$'; then
gh label create "visual-test" \
--description "Issues from automated visual regression tests" \
--color "E06C75"
fi
if ! gh label list --paginate --json name --jq '.[].name' | grep -q '^run-visual-test$'; then
gh label create "run-visual-test" \
--description "Run deterministic visual regression workflow on a PR" \
--color "E06C75"
fi
env:
GH_TOKEN: ${{ secrets.OPENCODE_PAT }}
Option B — gh label edit --force so it works whether the label exists or not
- name: Ensure visual-test label exists
run: |
gh label create "visual-test" \
--description "Issues from automated visual regression tests" \
--color "E06C75" || \
gh label edit "visual-test" \
--description "Issues from automated visual regression tests" \
--color "E06C75"
gh label create "run-visual-test" \
--description "Run deterministic visual regression workflow on a PR" \
--color "E06C75" || \
gh label edit "run-visual-test" \
--description "Run deterministic visual regression workflow on a PR" \
--color "E06C75"
env:
GH_TOKEN: ${{ secrets.OPENCODE_PAT }}
Option A keeps the original "skip if already present" intent and just makes the check correct. Option B also re-syncs the description/color on every run, which is slightly more invasive but never fails.
Either way, once this step succeeds, the workflow will reach step 10 and the real screenshot.png capture / golden-diff CI can finally run, so we can verify whether the underlying graphics stack is healthy.
Workflow run
https://github.com/OpenStaticFish/ZigCraft/actions/runs/29183938238
Symptom
The
visual-testworkflow fails at step 8 ("Ensure visual-test label exists") and never reaches step 10 ("Run menu screenshot capture"). As a result, noscreenshot.pngis produced and nobuild-output.logis written — every downstream step is skipped. This is the same failure observed on the previous scheduled run (#17, https://github.com/OpenStaticFish/ZigCraft/actions/runs/29143688205) and re-occurred on the run that produced this issue (#18).Relevant error output
From
0_visual-test.txtfor run #17 (the failure is byte-for-byte identical on run #18):Job step status for run #18 (current run):
Root cause
The pre-flight existence check in
.github/workflows/visual-test.yml:55-68is buggy:gh label list(without--paginateor a higher--limit) returns only the first 30 labels, sorted alphabetically. This repo now has 41 labels. Both target labels fall outside the first page when sorted alphabetically:Because
run-visual-testis past position 30 in the default page,grep -q '^run-visual-test$'exits 1, theif !inverts that to 0 (true), andgh label create "run-visual-test"runs — andgh label createerrors out because the label already exists:visual-testhappens to land at position 21, inside the default page, so that check is currently lucky. The bug is the same for both checks — onlyrun-visual-testis failing today because it sorts past the 30-item cutoff. As more labels are added to the repo,visual-testwill also drop off the first page and start failing.The check has been broken since the repo crossed 30 labels. It never had any effect on the
visual-testjob — it has always aborted before step 10 even ran — which is why nobuild-output.logexists in the diagnosis workspace for runs #17 and #18: the build was never invoked.(Note: issue #913 from run #17 was filed by the same diagnosis flow but misattributed the failure to "PPM screenshot capture is unsupported" because the build log was missing. The actual failure on that run — and on run #18 — is the label-creation error above. #913 should be closed once this issue is fixed.)
File / function where the failure originates
.github/workflows/visual-test.ymlEnsure visual-test label exists(lines 55-68)gh label create "run-visual-test"invoked on line 63, reached because the guard on line 62 returns the wrong answer when paginated.Suggested fix
Either fetch all labels so the guard sees the full list, or make the create itself idempotent. Either of the following edits to
.github/workflows/visual-test.ymlresolves the failure:Option A — paginate the list query (smallest change)
Option B —
gh label edit --forceso it works whether the label exists or notOption A keeps the original "skip if already present" intent and just makes the check correct. Option B also re-syncs the description/color on every run, which is slightly more invasive but never fails.
Either way, once this step succeeds, the workflow will reach step 10 and the real
screenshot.pngcapture / golden-diff CI can finally run, so we can verify whether the underlying graphics stack is healthy.