Skip to content

fix(whisper): extract MSVC runtime DLLs beside win32 whisper-server - #1687

Draft
greatcoat wants to merge 2 commits into
mainfrom
fix/bundle-whisper-crt-dlls
Draft

fix(whisper): extract MSVC runtime DLLs beside win32 whisper-server#1687
greatcoat wants to merge 2 commits into
mainfrom
fix/bundle-whisper-crt-dlls

Conversation

@greatcoat

Copy link
Copy Markdown
Contributor

Problem: Windows machines without the VC++ redistributable kill the CPU whisper-server at load with 0xC0000135 — every local dictation fails, empty stderr, before main().

Fix: Pin whisper.cpp 0.0.10 (first release bundling the MSVC runtime DLLs in its win32 zips) and extract those DLL companions beside the exe, reusing the llama/sherpa libPattern approach, now consolidated in lib/download-utils.

Important

Draft until OpenWhispr/whisper.cpp PR #6 merges and release 0.0.10 is cut — until that tag exists, any build from this branch fails to fetch the pinned release. Merging both + the release cut wait for Josh's explicit go.

Root cause

The win32 CPU whisper-server.exe links the dynamic MSVC runtime — its PE import table demands MSVCP140.dll, VCOMP140.DLL, VCRUNTIME140.dll, VCRUNTIME140_1.dll (the upstream build's CMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded static-CRT flag is a silent no-op without CMake policy CMP0091, and OpenMP links vcomp dynamically regardless) — but whisper-server-win32-x64-cpu.zip contained only the exe and download-whisper-cpp.js copied only the binary, unlike the llama/sherpa download scripts which both carry libPattern DLL companions. Nothing else provides the runtime: Electron's own copies live next to OpenWhispr.exe and are invisible to a child process in resources\bin, so on machines without the system-wide redist the loader terminates every spawn with 0xC0000135 (STATUS_DLL_NOT_FOUND).

Probe evidence (CUS-113, RCA in Titan wiki whisper-server-dll-not-found-rca.md): customer debug log debug-2026-08-17T12-23-22-137Z.log shows 14 spawns in ~8 s, each dead in ~50 ms with exit 3221225781 (=0xC0000135) across three models; PE import parse of the shipped 0.0.8/0.0.9 exes confirms the four CRT imports; zip listings confirm no DLLs shipped. Field-confirmed 2026-08-17: installing the VC++ redistributable — the only change — immediately fixed the reporting machine.

Fix

  • scripts/download-whisper-cpp.js — pin 0.0.10; win32-x64 config gains libPattern: "*.dll"; DLL companions are copied into resources/bin beside the exe (identical to the llama/sherpa pattern). main() is now guarded by require.main and the config exported, so the regression test can import the script without side effects.
  • scripts/lib/download-utils.js — new shared matchesPattern / findLibrariesInDir / copyLibraries; download-llama-server.js and download-sherpa-onnx.js had byte-identical private copies (whisper would have been the third), now consolidated.
  • src/helpers/whisperVulkanManager.js — win32 asset gains libPattern: /\.dll$/i so the 0.0.10 Vulkan zip's CRT DLLs are extracted at runtime too; its "statically linked — no companion libs" comment was wrong about the CRT and is corrected. No-op at 0.0.9 (zip has no DLLs).

Deliberate non-changes:

  • electron-builder.json — the extraResources filter already passes *.dll (the RCA's claim it blocks DLLs was stale on this point); no change needed.
  • cleanupFiles — already spares libraries (isLibrary guard) and only touches the whisper-server prefix; verified, untouched.
  • whisperCudaManager/whisperVulkanManager tag bumps to 0.0.10 + digests — the sha256 digest map can only be filled after the 0.0.10 assets exist; follow-up commit once the release is cut. CUDA's existing libPattern already extracts all zip DLLs, so it needs only the tag+digest bump.
  • NTSTATUS exit-code decoding, spawn circuit-breaker, app-version in debug header — separate hardening PRs (nice-to-haves from the RCA), not packaging.

Tests

  • RED (before the fix): test/scripts/downloadWhisperCpp.test.js fails — BINARIES["win32-x64"].libPattern is undefined, tag asserts '0.0.8' !== '0.0.10', copyLibraries is not a function.
  • GREEN: all 4 new tests pass; full suite npm test: 2094 tests, 1923 pass, 0 fail (170 skipped = known Electron-ABI better-sqlite3 local skips).
  • Packaged-app PE evidence + clean-Win10-VM RED/GREEN (0xC0000135 repro on current build → transcription on patched build) run once a 0.0.10-based build exists; tracked before release.

Provenance

RCA: Titan wiki/areas/engineering/whisper-server-dll-not-found-rca.md · Linear CUS-113 · customer thread 1a00fc15dfac3569 (Brian, Win10, free tier) · companion CI fix: OpenWhispr/whisper.cpp#6

🤖 Generated with Claude Code

The win32 CPU whisper-server.exe links the dynamic MSVC runtime
(msvcp140/vcruntime140/vcruntime140_1/vcomp140) but shipped as a bare exe:
download-whisper-cpp.js copied only the binary out of the release zip, so
on machines without the VC++ 2015-2022 redistributable the Windows loader
killed every spawn with 0xC0000135 (STATUS_DLL_NOT_FOUND) before main(),
with empty stderr — local transcription dead on arrival (CUS-113).

- pin whisper.cpp 0.0.10, the first release whose win32 zips bundle the DLLs
- give the win32 config the same libPattern DLL-companion extraction the
  llama/sherpa download scripts already use, consolidating their duplicated
  findLibrariesInDir/matchesPattern helpers into lib/download-utils.js
- prep whisperVulkanManager with libPattern so the 0.0.10 vulkan zip's CRT
  DLLs are extracted too (its "statically linked" comment was wrong re CRT)

electron-builder's extraResources filter already passes *.dll and
cleanupFiles already spares libraries, so no packaging-config change needed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants