Skip to content

qwen3_tts: hard crash (fail-fast 0xC0000409) on v0.9.1 release — works on the previous build with identical weights and command #836

Closed

Description

@laurentvv

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.
  • The same command, same weights, same reference audio, run on the previous local build (master 2892ed3, pre-Reduce Qwen3-TTS, IndexTTS, and BreezeTTS memory allocations #821) → exit 0 and a valid 84,524-byte wav.
  • 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

Happy to provide more details (ggml logs with a debug build, spec files, reference audio characteristics) if useful.

Activity

  1. 0xShug0 commented on Oct 8, 2026

    @0xShug0
    Owner

    @laurentvv Could you try audio-v0.9.1-bin-windows-x64-vulkan-portable.zip? Let me know if it works.

  2. laurentvv commented on Oct 8, 2026

    @laurentvv
    Author

    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:

    • standard audio-v0.9.1-bin-windows-x64-vulkan.zip: exit 3221225501 (0xC0000409), Vulkan and CPU, before any model-load log
    • portable audio-v0.9.1-bin-windows-x64-vulkan-portable.zip: exit 0, valid 24 kHz wav produced, correct French cloned speech

    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!

  3. laurentvv commented on Oct 8, 2026

    @laurentvv
    Author

    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):

    1. Build the standard Windows asset with the balance profile — runs on effectively every x64 CPU in use.
    2. 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.

  4. 0xShug0 commented on Oct 8, 2026

    @0xShug0
    Owner

    @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.

  5. laurentvv commented on Oct 8, 2026

    @laurentvv
    Author

    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.

  6. 0xShug0 commented on Oct 8, 2026

    @0xShug0
    Owner

    Roger that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions