Repository navigation
Conversation
A Unix signal death has no exit code, so a whisper-server killed by SIGILL at startup failed with "whisper-server process died during startup" and nothing else. The close handler now records the signal, and the startup error names it when the server printed nothing, as it already names a Windows exit code. Same names as the exit-signal capture in #2317, so the two merge cleanly. Refs #2356 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ut AVX2 The CPU whisper-server needs AVX2, FMA, F16C and BMI2, so on Intel processors before Haswell and on AMD FX it dies at startup with an illegal instruction (Windows exit code 3221225501, Unix SIGILL) and local Whisper never starts. When a CPU build dies that way, retry on the next build for older processors installed beside it (ivybridge: SSE4.2 + AVX + F16C, then sandybridge: SSE4.2 + AVX) and keep the one that starts for the rest of the session. The thread count retry no longer relaunches a build that crashed this way. With no build left, startup fails with a message saying the processor can't run it. Any other startup failure behaves as before. Refs #2356 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
BINARIES is now keyed by build, and each entry names the platform it belongs to, like download-llama-server.js. `--current` installs every build listed for the platform and fails the build when any of them is missing from the release, so a release without one of the builds for older processors can never ship without it. Each build keeps its own install marker; the existing builds keep their keys and marker names. Only the existing four builds are listed until the whisper.cpp release that adds the ivybridge and sandybridge builds is pinned. Refs #2356 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The two-repository plan behind this branch: the diagnosis, the whisper.cpp fork's ivybridge and sandybridge builds and their emulated checks, the desktop fallback and download changes, and what waits for the 0.0.11 release. Refs #2356 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s missing The builds for processors without AVX2 are what whisperServer.js falls back to when the primary dies of an illegal instruction, and nothing else notices one missing: a download step that installed only the primary would still exit 0. afterPack now fails the build when a fallback build that download-whisper-cpp.js lists for the platform is not in resources/bin. The primary is left to the download step, so local cross-arch packaging is unchanged, and the check is a no-op until the pinned release lists fallback builds. Refs #2356 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Until the whisper.cpp release with the builds for processors without AVX2 is pinned, none is installed, so the TROUBLESHOOTING line and the CLAUDE.md and code-comment claims about which platforms ship them were false at this commit. They move to the commit that pins the release; the CLAUDE.md entry now says each fallback tried is cached. The tests that spawn fake builds get a timeout, so a relaunch loop fails instead of hanging CI. The plan records the fork's startup level check and these changes. Refs #2356 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Refs #2356 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ot state From the test-quality review: - Each fake server gets an OS-assigned port. A fake that dies never binds its port, so with the manager's fixed range a second run of this file (another worktree) could answer its health check; two concurrent runs now pass. - The CUDA test proves the fallback session keeps its CPU server behaviourally: with a Vulkan pack installed, a later Vulkan request spawns nothing. It no longer reads gpuFallbackActive, which an extra stop() would have cleared. - The fallback builds' file names are pinned literally, so a Windows naming mistake fails a test before the release that ships the builds is pinned. Refs #2356 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In short: on PCs whose processor has AVX but not AVX2 (Intel 2nd/3rd-gen Core, AMD FX, older AMD A-series/Athlon, AMD Jaguar), local Whisper never starts. The bundled engine stops on its first AVX2-era instruction, and the user sees "whisper-server process died during startup: exit code: 3221225501". With this PR the app switches to a build made for those processors and keeps using it, so transcription works. It depends on new builds from OpenWhispr/whisper.cpp#8, so it stays a draft until that release is pinned (see Remaining).
Refs #2356. Also reported in #1418, #1613 and #793.
Problem
whisper-server-win32-x64.exeexits with 3221225501 =0xC000001D= STATUS_ILLEGAL_INSTRUCTION. The reports come from an i3-3110M, an i5-3570 and an unnamed AVX-only CPU.-ivb:SDE-ERROR: Executed instruction not valid for specified chip (IVYBRIDGE): 0x7ff6bfc6072d: shlx eax, edx, eax. The address ends inc072d, the same fault offset whisper-server-win32-x64.exe crashes with STATUS_ILLEGAL_INSTRUCTION (0xc000001d) on non-AVX2 CPUs, blocking GPU fallback path #1613's Event Viewer reported.-cpu IvyBridge: killed by SIGILL at startup.Root cause
The CPU
whisper-servercomes from OpenWhispr/whisper.cpp. It is statically linked and configured with-DGGML_NATIVE=OFF, which in ggml turns AVX2, FMA, F16C and BMI2 on. The 0.0.10 CI log prints/arch:AVX2 GGML_AVX2;GGML_FMA;GGML_F16C;__BMI2__;GGML_BMI2.A static build has no run-time CPU dispatch. It dies in
ggml_cpu_init()on a BMI2shlx, before the port binds.The
ggml-cpu-ivybridge.dllthat reporters found inresources/binbelongs to llama-server's llama.cpp bundle.whisper-serverimports no ggml DLL, so it never uses it.Fix
whisper.cpp (OpenWhispr/whisper.cpp#8):
ivybridge(SSE4.2 + AVX + F16C) andsandybridge(SSE4.2 + AVX) levels.This PR:
whisperServer.jsnames the signal when the server dies at startup. A SIGILL used to leave no detail at all. It uses the same names as the exit-signal capture in fix(whisper): save and show why GPU acceleration fell back to CPU #2317._doStartretries on the next build inCPU_FALLBACK_LEVELS(ivybridge, thensandybridge) installed next to the build that died.cachedServerBinaryPath, so later starts in the session (restarts, model or VAD changes, GPU→CPU fallbacks) never re-run a build that crashed.whisper-server can't run on this processor: … (exit code: 3221225501) ….download-whisper-cpp.jsinstalls every build a platform lists. Entries are keyed per build with aplatformArch, likedownload-llama-server.js, and each build has its own install marker. A release missing any listed build fails--current. Today's four builds, their markers and their output are unchanged.resources/bin. The primary build is left to the download step.Why two levels: without F16C, ggml converts fp16 weights one at a time through a lookup table. In local x86 runs (Rosetta, ratios only), the sandybridge build was about 7× slower than ivybridge, and every processor named in the reports has F16C.
Why a startup check in the fork: the first emulated run showed the ivybridge build starting and serving on a Sandy Bridge. ggml's startup code never touches F16C, so the build would only have crashed mid-transcription, where no fallback can see it. The check makes "dies at startup" a guarantee rather than an accident of ggml's init code. It is enabled only for the new builds, because Rosetta 2 (and some hypervisors) hide AVX in CPUID yet run it, and the existing build must behave exactly as before.
Deliberately untouched:
.env. The primary's crash costs about 0.1–0.5 s once per launch, during pre-warm.Tests
test/helpers/whisperServerCpuFallback.test.jshas 11 tests. They spawn fake builds (shell scripts that die by SIGILL or SIGSEGV, or serve HTTP) through the real start path:stop();Results:
whisper-server process died during startup.test/scripts/afterPackWhisperServerBuilds.test.jsand the newdownloadWhisperCpptests cover the required-builds rule.--currentdownload of 0.0.10 installs exactly what it did before.The full
npm testlocally fails only in editor, markdown and chat suites, which needhappy-dom/remark-gfmabsent from that machine'snode_modules. CI's clean install is the authoritative run.Independent review: a read-only deep review covered the whole branch. It found no correctness issue; its doc, backstop and timeout findings are fixed in the last two commits.
Merging with #2317
There is one conflict, in
whisperServer.js. Both PRs add the identicalexitSignalandgetProcessInfolines, and #2317 also addsthis._lastProcessInfo = getProcessInfo;. Take #2317's side of that hunk; keeping both declaresexitSignaltwice. Everything else merges cleanly in either order.Remaining (why this is a draft)
Review and merge build: whisper-server for processors without AVX2 (ivybridge, sandybridge) whisper.cpp#8, then publish 0.0.11 from master. Its
verify-cpu-levelsjob must pass first.The final commit on this branch:
WHISPER_CPP_TAGto 0.0.11;Until then this branch finds no fallback build, and such a CPU gets the clearer error.
After the app release ships, issues whisper-server crashes with Illegal Instruction (0xC000001D) on Ivy Bridge CPU (no AVX2) #2356, whisper-server-win32-x64.exe crashes with STATUS_ILLEGAL_INSTRUCTION (0xC000001D) on Intel Ivy Bridge (i5-3570) #1418, whisper-server-win32-x64.exe crashes with STATUS_ILLEGAL_INSTRUCTION (0xc000001d) on non-AVX2 CPUs, blocking GPU fallback path #1613 and OpenWhispr local whisper-server crashes with SIGILL on AMD FX-8350 #793 can be closed by hand.
Not verified
Follow-ups:
parakeetWsServer.jsandqdrantManager.jsalso drop the signal on a signal death.Plan:
docs/superpowers/plans/2026-09-28-no-avx2-cpu-fallback.md🤖 Generated with Claude Code