Summary
When zccache's daemon-control named pipe is orphaned (PID gone, pipe handle still locked by Windows), the bash compile / bash autoresearch wrapper around fbuild exits with ❌ Compilation failed (fbuild) [0.0s] and the diagnostic banner (fbuild executable: ..., running-process broker: direct daemon fallback ...), but the actual error message is swallowed. The real cause is only visible by running fbuild directly against the build dir:
zccache[err][D]: cannot start daemon at \\.\pipe\zccache-Zach_Vorhies-0d204d7e:
daemon process 55872 exists but not accepting connections
That message tells the user exactly what to fix (clean up the orphaned pipe / kill the dead PID's pipe handle). The wrapped invocation hides it, leaving the user with "build failed in 0.0s" and no actionable diagnostic. The user spent significant cycles diagnosing this on an LPC845 bring-up bench before noticing the silent failure pattern was the same on bash compile esp32s3 --examples Blink -- ruling out the LPC platform and isolating it to fbuild's CLI error-surfacing.
Reproduction
# 1. Trigger the orphan: kill a zccache daemon mid-build (or hit the underlying
# race where the daemon dies but its Windows named pipe stays locked).
taskkill /F /PID <zccache-daemon-pid>
# 2. Subsequent fbuild builds via the wrapper bail in 0.0s with no real error:
bash compile esp32s3 --examples Blink
# Output:
# unsupported platform:
# fbuild executable: ...
# fbuild version: 2.2.28
# running-process broker: direct daemon fallback (running-process broker client stubbed)
# ❌ Compilation failed (fbuild) [0.0s]
# 3. The actual diagnostic is only visible by running fbuild directly:
cd .build/pio/lpc845brk
~/dev/fastled5/.venv/Scripts/fbuild.exe . build -e lpc845brk
# build error: build failed: compilation failed for .\.fbuild\build\lpc845brk\release\src\Sailboat.ino.cpp:
# zccache[err][D]: cannot start daemon at \\.\pipe\zccache-Zach_Vorhies-0d204d7e:
# daemon process 55872 exists but not accepting connections
What the wrapper / CLI should do
-
Surface the zccache error to the user. The string zccache[err][D]: cannot start daemon at ...: daemon process N exists but not accepting connections is highly actionable. Whatever layer is capturing fbuild's stderr (the ci/compile.py wrapper, or fbuild's own CLI when it spawns the daemon) should propagate it to the foreground build output, not just drop "Compilation failed (fbuild) [0.0s]" on the floor.
-
Optionally: auto-recover. fbuild already does the "found stale daemon PID file pointing at dead PID N; cleaning up" pattern for its own daemon -- see ~/.fbuild/prod/daemon/daemon.log:
WARN fbuild_daemon: found stale daemon PID file pointing at dead PID 76384; cleaning up
The same recovery shape would be appropriate for the zccache daemon-control pipe -- detect the dead PID, remove the orphaned named-pipe handle, retry.
-
Bail-time vs banner-time. The "unsupported platform: " line followed by the diagnostic banner is printed even on success, so users learn to ignore it. When the build then says "❌ Compilation failed (fbuild) [0.0s]" with no further error text, the natural assumption is the diagnostic banner contains the error (it doesn't), or that the failure is in the unsupported platform: field (it isn't -- that's a bug-report-friendly summary that happens to be empty for non--x invocations). At minimum, when exit != 0, the wrapper should re-print stderr it captured from the fbuild subprocess.
Related
Hardware/env
- Host: Windows 10 19045, MSYS2 bash
- fbuild 2.2.28 (PyPI), also reproduced with fbuild 2.2.29 (editable install from
~/dev/fbuild2)
- zccache 1.12.7 (via the FastLED pyproject pin) AND zccache 1.12.4 (vendored by fbuild's
~/.fbuild/prod/bin/zccache-1.12.4/zccache.exe)
- Trigger was
taskkill /F /PID <zccache-daemon-pid> mid-session followed by a fresh bash compile attempt -- the new fbuild invocation tried to connect to the now-dead pipe.
Filed via Claude Code on behalf of zachvorhies@protonmail.com.
Summary
When zccache's daemon-control named pipe is orphaned (PID gone, pipe handle still locked by Windows), the
bash compile/bash autoresearchwrapper around fbuild exits with❌ Compilation failed (fbuild) [0.0s]and the diagnostic banner (fbuild executable: ...,running-process broker: direct daemon fallback ...), but the actual error message is swallowed. The real cause is only visible by runningfbuilddirectly against the build dir:That message tells the user exactly what to fix (clean up the orphaned pipe / kill the dead PID's pipe handle). The wrapped invocation hides it, leaving the user with "build failed in 0.0s" and no actionable diagnostic. The user spent significant cycles diagnosing this on an LPC845 bring-up bench before noticing the silent failure pattern was the same on
bash compile esp32s3 --examples Blink-- ruling out the LPC platform and isolating it to fbuild's CLI error-surfacing.Reproduction
What the wrapper / CLI should do
Surface the zccache error to the user. The string
zccache[err][D]: cannot start daemon at ...: daemon process N exists but not accepting connectionsis highly actionable. Whatever layer is capturing fbuild's stderr (theci/compile.pywrapper, or fbuild's own CLI when it spawns the daemon) should propagate it to the foreground build output, not just drop "Compilation failed (fbuild) [0.0s]" on the floor.Optionally: auto-recover. fbuild already does the "found stale daemon PID file pointing at dead PID N; cleaning up" pattern for its own daemon -- see
~/.fbuild/prod/daemon/daemon.log:The same recovery shape would be appropriate for the zccache daemon-control pipe -- detect the dead PID, remove the orphaned named-pipe handle, retry.
Bail-time vs banner-time. The "unsupported platform: " line followed by the diagnostic banner is printed even on success, so users learn to ignore it. When the build then says "❌ Compilation failed (fbuild) [0.0s]" with no further error text, the natural assumption is the diagnostic banner contains the error (it doesn't), or that the failure is in the
unsupported platform:field (it isn't -- that's a bug-report-friendly summary that happens to be empty for non--xinvocations). At minimum, when exit != 0, the wrapper should re-print stderr it captured from the fbuild subprocess.Related
zccache>=1.12.7, well past 1.11.16, so the underlying detection should be in place -- but the error-message propagation issue is independent.Hardware/env
~/dev/fbuild2)~/.fbuild/prod/bin/zccache-1.12.4/zccache.exe)taskkill /F /PID <zccache-daemon-pid>mid-session followed by a freshbash compileattempt -- the new fbuild invocation tried to connect to the now-dead pipe.Filed via Claude Code on behalf of zachvorhies@protonmail.com.