Workflow
https://github.com/OpenStaticFish/ZigCraft/actions/runs/30192579914
Failure output
The visual-test job fails at the Ensure visual-test label exists step (2026-07-26T07:18:58Z schedule run). Subsequent steps including Run menu screenshot capture are skipped because the workflow uses if: success() on them, so build-output.log is never produced. The screenshot / Vulkan / PPM path therefore never runs.
The "failure output" block referenced by .github/prompts/visual-test-diagnose.md does not exist in the workspace, which is the expected symptom of this preflight failure — the prompt's hypothesis (screenshot.ppm rejected by detectScreenshotFormat) is not what the run actually does. .github/workflows/visual-test.yml:81 invokes zig build run -Dscreenshot-path=screenshot.png -Dskip-present=true, and screenshot.zig:262-267 only rejects the format the prompt fabricates (.ppm).
Reference failure from the previous day's run (identical error, full stderr):
label with name "run-visual-test" already exists; use `--force` to update its color and description
##[error]Process completed with exit code 1.
The same message is emitted by the Ensure visual-test label exists step in run 30192579914 (logs not yet accessible because the job is still in its post-failure diagnosis phase, but the job summary shows that step as the only failure X while every later step is - / skipped).
Diagnosis
The visual-test workflow does not fail in the Vulkan / screenshot capture path. The Zig build and Lavapipe screenshot run never execute because the preflight gh label list / gh label create step exits non-zero, which causes every later step (including Run menu screenshot capture and Check build log exists) to be skipped. build-output.log therefore does not exist in the workspace because the run-with-log action never ran.
Root cause is in .github/workflows/visual-test.yml:55-68 (Ensure visual-test label exists):
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 paginates with a default page size of 30 and --jq '.[].name' only emits the first page. Once the repo accumulates enough labels that run-visual-test falls off page 1, the grep -q '^run-visual-test$' returns 1 and the workflow tries to recreate it; gh label create then errors with label with name "run-visual-test" already exists; use --force to update its color and description. Either branch causes set -e to abort the step with exit code 1.
This is the same failure that has been hitting the visual-test workflow every day since at least 2026-07-12 — see #916, #931, #935, #942, #944, #945, #946, #947, #949, #950. Issue #950 was filed for the previous day's run (30148576016) and is still open.
The stale .github/prompts/visual-test-diagnose.md (lines 7, 8, 9, 21, 42, 43) keeps misdirecting the diagnosis agent at a non-existent PPM failure every time build-output.log is missing, which has led to at least two duplicate / misdiagnosed issues (#949, and the rejected comment on #950).
Origin of the failure
- File:
.github/workflows/visual-test.yml
- Step:
Ensure visual-test label exists (lines 55-68)
- Function:
gh label list --json name --jq '.[].name' — paginated, only the first 30 labels returned
- Logic:
if ! ... grep -q '^run-visual-test$'; then gh label create ...; fi — recreates an already-existing label once it falls off page 1
Suggested fix
Either fetch all pages when listing labels, or make gh label create failures non-fatal:
if ! gh label list --json name --jq '.[].name' --paginate | grep -q '^visual-test$'; then
gh label create "visual-test" \
--description "Issues from automated visual regression tests" \
--color "E06C75" || true
fi
if ! gh label list --json name --jq '.[].name' --paginate | grep -q '^run-visual-test$'; then
gh label create "run-visual-test" \
--description "Run deterministic visual regression workflow on a PR" \
--color "E06C75" || true
fi
Adding --paginate ensures run-visual-test is found on later pages, and || true on the create calls makes the step idempotent against transient gh label create failures (network/API errors, partial outages that have been seen in earlier runner logs with Failed to restore: Cache service responded with 400 / Our services aren't available right now). After the fix, the actual Lavapipe / headless-swapchain / PNG screenshot capture path (headless swapchain at modules/engine-graphics/src/vulkan_swapchain.zig:127-174, PNG writer at modules/engine-graphics/src/vulkan/screenshot.zig:279-349, frame counting at src/game/app.zig:528-593) can finally be exercised end-to-end and reported on its own merits.
.github/prompts/visual-test-diagnose.md should also be updated to reference -Dscreenshot-path=screenshot.png (and screenshot.png) instead of screenshot.ppm so future diagnosis agents don't fabricate PPM-rejection output.
Workflow
https://github.com/OpenStaticFish/ZigCraft/actions/runs/30192579914
Failure output
The
visual-testjob fails at theEnsure visual-test label existsstep (2026-07-26T07:18:58Zschedule run). Subsequent steps includingRun menu screenshot captureare skipped because the workflow usesif: success()on them, sobuild-output.logis never produced. The screenshot / Vulkan / PPM path therefore never runs.The "failure output" block referenced by
.github/prompts/visual-test-diagnose.mddoes not exist in the workspace, which is the expected symptom of this preflight failure — the prompt's hypothesis (screenshot.ppmrejected bydetectScreenshotFormat) is not what the run actually does..github/workflows/visual-test.yml:81invokeszig build run -Dscreenshot-path=screenshot.png -Dskip-present=true, andscreenshot.zig:262-267only rejects the format the prompt fabricates (.ppm).Reference failure from the previous day's run (identical error, full stderr):
The same message is emitted by the
Ensure visual-test label existsstep in run30192579914(logs not yet accessible because the job is still in its post-failure diagnosis phase, but the job summary shows that step as the only failureXwhile every later step is-/ skipped).Diagnosis
The visual-test workflow does not fail in the Vulkan / screenshot capture path. The Zig build and Lavapipe screenshot run never execute because the preflight
gh label list / gh label createstep exits non-zero, which causes every later step (includingRun menu screenshot captureandCheck build log exists) to be skipped.build-output.logtherefore does not exist in the workspace because the run-with-log action never ran.Root cause is in
.github/workflows/visual-test.yml:55-68(Ensure visual-test label exists):gh label listpaginates with a default page size of 30 and--jq '.[].name'only emits the first page. Once the repo accumulates enough labels thatrun-visual-testfalls off page 1, thegrep -q '^run-visual-test$'returns 1 and the workflow tries to recreate it;gh label createthen errors withlabel with name "run-visual-test" already exists; use --force to update its color and description. Either branch causesset -eto abort the step with exit code 1.This is the same failure that has been hitting the visual-test workflow every day since at least 2026-07-12 — see #916, #931, #935, #942, #944, #945, #946, #947, #949, #950. Issue #950 was filed for the previous day's run (
30148576016) and is still open.The stale
.github/prompts/visual-test-diagnose.md(lines 7, 8, 9, 21, 42, 43) keeps misdirecting the diagnosis agent at a non-existent PPM failure every timebuild-output.logis missing, which has led to at least two duplicate / misdiagnosed issues (#949, and the rejected comment on #950).Origin of the failure
.github/workflows/visual-test.ymlEnsure visual-test label exists(lines 55-68)gh label list --json name --jq '.[].name'— paginated, only the first 30 labels returnedif ! ... grep -q '^run-visual-test$'; then gh label create ...; fi— recreates an already-existing label once it falls off page 1Suggested fix
Either fetch all pages when listing labels, or make
gh label createfailures non-fatal:Adding
--paginateensuresrun-visual-testis found on later pages, and|| trueon the create calls makes the step idempotent against transientgh label createfailures (network/API errors, partial outages that have been seen in earlier runner logs withFailed to restore: Cache service responded with 400/Our services aren't available right now). After the fix, the actual Lavapipe / headless-swapchain / PNG screenshot capture path (headless swapchain atmodules/engine-graphics/src/vulkan_swapchain.zig:127-174, PNG writer atmodules/engine-graphics/src/vulkan/screenshot.zig:279-349, frame counting atsrc/game/app.zig:528-593) can finally be exercised end-to-end and reported on its own merits..github/prompts/visual-test-diagnose.mdshould also be updated to reference-Dscreenshot-path=screenshot.png(andscreenshot.png) instead ofscreenshot.ppmso future diagnosis agents don't fabricate PPM-rejection output.