fix(core): ort-silero VAD init panic degrades to whisper-silero instead of crashing the recording sidecar (#408)#409
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Jul 3, 2026
Merged
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.
Closes #408.
Incident
A live recording on the SOTA dev build (
parakeet,metal,vad-ort,engine-sherpa) died mid-meeting:live-transcript-status.jsonshowedstate: failed,diagnostic: "sidecar panicked: Failed to initialize ORT API". The mic kept recording to WAV the whole time — only the live-transcript sidecar crashed. Config hadvad_engine = "ort-silero"; the previous dev build didn't compilevad-ortso it silently fell back, but the SOTA build actually tried to init ORT and theortcrate panicked (OrtGetApiBase().GetApi()→ null →.expect("Failed to initialize ORT API")) instead of returning an error — below theResultboundary the fallback chain relied on.Fix
A VAD init failure must never crash a live recording.
OrtSileroVad::new_catching_unwindwraps construction incatch_unwind, converting a panic intoOrtSileroError::Panic, so ORT init failure now follows the same recoverable path as a missing model or an uncompiled feature: ort-silero → whisper-silero → energy, with an honesttracing::warn!. Same honest-degradation principle as #395/#396. Regression testort_silero_init_panic_falls_back_to_whisper_sileroinjects the exact incident panic and asserts fallback toSilerowith nothing escaping.Review
Fresh-context adversarial review found no blockers:
AssertUnwindSafenarrowly scoped to construction; ort's global API pointer usesOnceLock/call_once_force(a caught init panic isn't permanently poisoned); whisper-silero uses whisper-rs (no ort), isolating the fallback. Tests (vad-ort,streaming+--no-default-features), fmt, clippy green.Root cause: narrowed, not fixed here
The two-static-onnxruntime hypothesis was refuted in
cargo test— co-compilingengine-sherpa+vad-ortstill inits ORT fine in a debug binary. The panic only manifests in the packaged, signed .app process (release linkage + init order), so root-causing needs an app-bundle repro. Tracked on #408, feeds #369. This PR closes the incident class regardless.🤖 Generated with Claude Code