whisper : catch C++ exceptions in whisper_init_with_params_no_state#3831
Merged
danbev merged 1 commit intoJun 2, 2026
Merged
Conversation
whisper_model_load() can throw instead of returning false: std::runtime_error from this file (failed ggml context / no compatible buffer type), or vk::SystemError / vk::OutOfDeviceMemoryError from the ggml-vulkan backend during device/buffer allocation. whisper_init_* are extern "C", so a C++ exception unwinding across that boundary aborts non-C++ callers (Rust via whisper-rs, Go via cgo) -- on Windows STATUS_STACK_BUFFER_OVERRUN (0xC0000409) -- even though the function already returns NULL on failure. Wrap whisper_model_load() in try/catch and route any throw into the existing NULL-return path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
danbev
approved these changes
Jun 2, 2026
danbev
added a commit
to danbev/whisper.cpp
that referenced
this pull request
Jun 2, 2026
This commit adds exception handling to the parakeet_model_load function call. The motivation for this is to avoid exceptions being thrown from this function as it is part of the extern C interface and instead log the error and return nullptr. Refs: ggml-org#3831
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.
Problem
whisper_init_with_params_no_stateisextern "C"and already reports failure by returningNULL(theif (!whisper_model_load(...))branch). Butwhisper_model_loadcan throw instead of returningfalse:std::runtime_errorfromsrc/whisper.cppitself (e.g. "failed to create ggml context", "failed to find a compatible buffer type for tensor ...").vk::SystemError/vk::OutOfDeviceMemoryErrorfrom the ggml-vulkan backend during device/buffer allocation (ggml_vk_create_buffer→device.allocateMemory, and logical-devicecreateDevice).Because
whisper_init_*areextern "C", a C++ exception unwinding across that boundary into a non-C++ caller aborts the process. From Rust (whisper-rs) the failure looks like:and the process exits with
STATUS_STACK_BUFFER_OVERRUN (0xC0000409)on Windows. A recoverable backend/init error thus becomes a hard crash the caller cannot handle — even though the function is designed to report failure viaNULL.Observed
Loading a GGML model on a Vulkan backend that transiently fails device init at startup —
vk::PhysicalDevice::createDevice: ErrorInitializationFailedon an NVIDIA RTX 5090 during the first Vulkan device bring-up — aborts the host process instead of returningNULL. A load attempt moments later succeeds, so it is a recoverable transient.Fix
Wrap the
whisper_model_loadcall in try/catch and funnel any throw into the existingNULL-return path. This keeps the documented "returns NULL on failure" contract for every failure mode and guarantees no C++ exception crosses theextern "C"boundary. Callers already handleNULL(e.g.whisper_init_from_file_with_params, and the language bindings), so a backend failure now degrades to a normal init error instead of aborting the host.whisper_init_from_{file,buffer}_with_params_no_stateboth build awhisper_model_loaderand route throughwhisper_init_with_params_no_state, so this single guard covers both entry points.No behavior change on success; only
throw → abortbecomesthrow → NULL.