You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
qwen3_tts: hard crash (fail-fast 0xC0000409) on v0.9.1 release — works on the previous build with identical weights and command #836
Title: qwen3_tts: hard crash (fail-fast 0xC0000409) at load on v0.9.1 release — works on the previous build with identical weights and command
Body:
Environment
audio.cpp v0.9.1, official release asset audio-v0.9.1-bin-windows-x64-vulkan.zip (58.68 MB)
Windows 11 x64, AMD Radeon RX 6950 XT (Vulkan, proprietary driver) — also reproduces with --backend cpu
Model: Qwen3-TTS-12Hz-1.7B-Base-GGUF/qwen3-tts-12hz-1.7b-base-q8_0_v2.gguf (2,695,175,104 bytes, byte-identical to the current audio-cpp/audio.cpp-gguf org copy)
Command
audiocpp_cli.exe --task tts --family qwen3_tts \
--model C:\Modeles_LLM\Qwen3-TTS-12Hz-1.7B-Base-GGUF\qwen3-tts-12hz-1.7b-base-q8_0_v2.gguf \
--backend vulkan \
--text "Test." \
--out out.wav --language French \
--voice-ref ref.wav --reference-text "Ceci est un test de ma voix."
Behavior
Exit code 3221225501 (0xC0000409, Windows fail-fast / illegal instruction) before any model-load log line — stdout/stderr contain only the ggml Vulkan device banner. Same failure with --backend cpu.
Other families on the same v0.9.1 binary work (checked: owsm v4-small ASR, qwen3_asr — both exit 0 with correct transcripts).
Notes / suspicion
The only commit in the v0.9.0→v0.9.1 range touching the qwen3_tts path is Reduce Qwen3-TTS, IndexTTS, and BreezeTTS memory allocations #821 ("Reduce Qwen3-TTS, IndexTTS, and BreezeTTS memory allocations"); the new model_specs/qwen3_tts.json adds the *_graph_arena_mb / *_weight_type session knobs. Not confirmed — black-box observation only.
Same machine (Windows 11 x64, RX 6950 XT Vulkan), same weights (qwen3-tts-12hz-1.7b-base-q8_0_v2.gguf, byte-identical to the org copy), the exact command that crashed on the standard zip:
standard audio-v0.9.1-bin-windows-x64-vulkan.zip: exit 3221225501 (0xC0000409), Vulkan and CPU, before any model-load log
Both exes report audio.cpp 0.9.1 / git cf124a67 / msvc 19.44. The portable audiocpp_cli.exe is slightly larger (82,832,896 vs 81,653,248 bytes), consistent with the CRT being linked differently — sounds like the fail-fast came from the dynamic-runtime packaging specifically.
Thanks for the quick turnaround — much appreciated!
Root cause found: the standard Windows zip contains unguarded AVX-512 instructions — it crashes with STATUS_ILLEGAL_INSTRUCTION on any CPU without AVX-512.
We ran the standard exe under a debugger (cdb) on the failing command:
The faulting exception is 0xC000001D STATUS_ILLEGAL_INSTRUCTION (I mislabeled it 0xC0000409 in my original report — the process exit code 3221225501 is in fact 0xC000001D; correcting the record here).
The faulting instruction at audiocpp_cli+0x11c8855 is vmovups zmm0, zmmword ptr [...] — an AVX-512 (ZMM-register) instruction. Our i7-13700KF (Raptor Lake) has AVX2 but no AVX-512, hence the immediate kill during qwen3_tts session init (before any model-load log). Families whose init path never executes those vectorized loops (owsm, qwen3_asr) run fine on the same binary.
Why the portable works: profile baseline (packaging script: portable = baseline arch, llamafile OFF) — no AVX of any kind in the binary.
Additional controls, all from the same source tag cf124a67, same machine (RX 6950 XT + i7-13700KF):
Build
Toolset
Profile
qwen3_tts
standard release zip
19.44.35229
contains AVX-512 code
❌ STATUS_ILLEGAL_INSTRUCTION (vmovups zmm0)
portable release zip
19.44.35229
baseline
✅
our build
19.51
avx2 + llamafile ON + deployment
✅
our build
19.44.35229 (same toolset as yours)
avx2 + llamafile ON + deployment
✅
So it is neither the compiler version nor the dynamic-CRT packaging: the standard asset appears to have been built with the fast/native profile on an AVX-512-capable build host, leaving unguarded AVX-512-autovectorized code in the binary. The packaging script's default profile is balance (AVX2 ceiling) — the standard asset probably should be that.
Suggested fixes (either one works):
Build the standard Windows asset with the balance profile — runs on effectively every x64 CPU in use.
Or keep fast, but restrict /arch:AVX512 to runtime-dispatched ggml kernel TUs and compile the app/model code at /arch:AVX2 (ggml's CPUID dispatch then protects everything else).
Impact scope: every AVX-512-less CPU — which includes all consumer Intel 12th-14th gen (Alder/Raptor Lake), so a fair share of users. Happy to re-test a rebuilt standard asset same-day; if you share the standard build's PDB I can also map +0x11c8855 to the exact function for you.
@laurentvv Thanks for confirming. Yes, that’s the root cause. We’ve seen this issue before. The CPU architecture was selected automatically based on the GitHub runner, and the recent build picked AVX-512. GitHub may have upgraded its runner infrastructure. The portable release explicitly targets AVX2. The pipeline isn’t on main yet; it and other CI changes are still being tested and will be merged for the next release.
Thanks for the confirmation and the quick close — that matches everything we measured under the debugger.
One small data point that may matter for the upcoming CI pipeline: we inspected the current vulkan-portable asset and it is baseline — no AVX/AVX2 instructions in the binary at all (that's why it runs here). If the new pipeline floors the portable build at AVX2, CPUs without AVX2 (Sandy Bridge → Haswell, Zen 1 / Zen+) would hit the exact same STATUS_ILLEGAL_INSTRUCTION crash. Keeping the portable floor at baseline (or gating the arch flags per-target) would keep it truly portable.
On our side we've switched production to the portable zip in the meantime — qwen3_tts and the ASR families all pass on it.
Activity
docs(veille): qwen3_tts regression issue POSTED upstream on explicit …
0xShug0 commentedon Oct 8, 2026
@laurentvv Could you try audio-v0.9.1-bin-windows-x64-vulkan-portable.zip? Let me know if it works.
laurentvv commentedon Oct 8, 2026
Confirmed — the portable build fixes it. 🎉
Same machine (Windows 11 x64, RX 6950 XT Vulkan), same weights (
qwen3-tts-12hz-1.7b-base-q8_0_v2.gguf, byte-identical to the org copy), the exact command that crashed on the standard zip:audio-v0.9.1-bin-windows-x64-vulkan.zip: exit3221225501(0xC0000409), Vulkan and CPU, before any model-load logaudio-v0.9.1-bin-windows-x64-vulkan-portable.zip: exit 0, valid 24 kHz wav produced, correct French cloned speechBoth exes report
audio.cpp 0.9.1 / git cf124a67 / msvc 19.44. The portableaudiocpp_cli.exeis slightly larger (82,832,896 vs 81,653,248 bytes), consistent with the CRT being linked differently — sounds like the fail-fast came from the dynamic-runtime packaging specifically.Thanks for the quick turnaround — much appreciated!
laurentvv commentedon Oct 8, 2026
Root cause found: the standard Windows zip contains unguarded AVX-512 instructions — it crashes with STATUS_ILLEGAL_INSTRUCTION on any CPU without AVX-512.
We ran the standard exe under a debugger (cdb) on the failing command:
0xC000001DSTATUS_ILLEGAL_INSTRUCTION (I mislabeled it0xC0000409in my original report — the process exit code 3221225501 is in fact0xC000001D; correcting the record here).audiocpp_cli+0x11c8855isvmovups zmm0, zmmword ptr [...]— an AVX-512 (ZMM-register) instruction. Our i7-13700KF (Raptor Lake) has AVX2 but no AVX-512, hence the immediate kill during qwen3_tts session init (before any model-load log). Families whose init path never executes those vectorized loops (owsm,qwen3_asr) run fine on the same binary.Why the portable works: profile
baseline(packaging script: portable = baseline arch, llamafile OFF) — no AVX of any kind in the binary.Additional controls, all from the same source tag
cf124a67, same machine (RX 6950 XT + i7-13700KF):vmovups zmm0)So it is neither the compiler version nor the dynamic-CRT packaging: the standard asset appears to have been built with the fast/native profile on an AVX-512-capable build host, leaving unguarded AVX-512-autovectorized code in the binary. The packaging script's default profile is
balance(AVX2 ceiling) — the standard asset probably should be that.Suggested fixes (either one works):
balanceprofile — runs on effectively every x64 CPU in use.fast, but restrict/arch:AVX512to runtime-dispatched ggml kernel TUs and compile the app/model code at/arch:AVX2(ggml's CPUID dispatch then protects everything else).Impact scope: every AVX-512-less CPU — which includes all consumer Intel 12th-14th gen (Alder/Raptor Lake), so a fair share of users. Happy to re-test a rebuilt standard asset same-day; if you share the standard build's PDB I can also map
+0x11c8855to the exact function for you.0xShug0 commentedon Oct 8, 2026
@laurentvv Thanks for confirming. Yes, that’s the root cause. We’ve seen this issue before. The CPU architecture was selected automatically based on the GitHub runner, and the recent build picked AVX-512. GitHub may have upgraded its runner infrastructure. The portable release explicitly targets AVX2. The pipeline isn’t on main yet; it and other CI changes are still being tested and will be merged for the next release.
laurentvv commentedon Oct 8, 2026
Thanks for the confirmation and the quick close — that matches everything we measured under the debugger.
One small data point that may matter for the upcoming CI pipeline: we inspected the current
vulkan-portableasset and it is baseline — no AVX/AVX2 instructions in the binary at all (that's why it runs here). If the new pipeline floors the portable build at AVX2, CPUs without AVX2 (Sandy Bridge → Haswell, Zen 1 / Zen+) would hit the exact sameSTATUS_ILLEGAL_INSTRUCTIONcrash. Keeping the portable floor at baseline (or gating the arch flags per-target) would keep it truly portable.On our side we've switched production to the portable zip in the meantime — qwen3_tts and the ASR families all pass on it.
0xShug0 commentedon Oct 8, 2026
Roger that!