cjpais/Handy · error · anyhow::Error

transcribe-cpp transcription failed

Error message

transcribe-cpp transcription failed: {}

What it means

The whisper-family path calls session.run(&audio, &run_options) on the loaded transcribe-cpp GGML session; this error wraps any run failure with the library's chained message. Common causes are a run extension rejected by the loaded architecture (e.g. a non-whisper arch like Voxtral rejecting the whisper-kind extension with INVALID_ARG, issue #1601), GGML backend/GPU errors, or invalid input state.

Solutions

  1. Read the chained transcribe-cpp error text — INVALID_ARG on the run extension means the arch rejects whisper-specific options; disable translate/custom-words prompt for that model
  2. Switch the transcribe accelerator setting to CPU to rule out GPU/VRAM issues
  3. Reload the model (unload + load) to rebuild a possibly broken GGML context
  4. Update Handy / transcribe-cpp if the arch is newly supported
  5. Verify the recording pipeline produces sane f32 PCM (check audio device and resampler settings)

Example fix

// before: always attach the whisper run extension
let ext = WhisperRunOptions { translate, initial_prompt, ..Default::default() };
run_options.extension = Some(RunExtension::Whisper(ext));

// after: gate the whisper-kind extension on the arch (see #1601)
if model_is_whisper {
    run_options.extension = Some(RunExtension::Whisper(ext));
}
Defensive patterns

Strategy: try-catch

Validate before calling

// gate whisper-only run options on the loaded arch before transcribe()
if !model_is_whisper {
    run_options.extension = None; // avoid INVALID_ARG from non-whisper archs (#1601)
}

Try / catch

match manager.transcribe(audio) {
    Err(e) if e.to_string().contains("transcribe-cpp transcription failed") => {
        // inspect chained cause: provider error -> switch backend; INVALID_ARG -> drop whisper extension
        if e.to_string().contains("INVALID_ARG") { disable_prompt_and_translate(); }
        manager.transcribe(audio) // single retry after remediation
    }
    other => other,
}

Prevention

When it happens

Trigger: Loading a non-whisper GGUF that advertises InitialPrompt but rejects the whisper run extension; enabling translate or prompt options the loaded arch does not support; GPU backend returning an error mid-inference (context lost, out of VRAM); audio buffer malformed (all-zero/NaN samples after bad resampling).

Common situations: Using Voxtral or other new GGUF archs with whisper-only features enabled; VRAM exhausted by another app; driver reset; mismatched transcribe-cpp version after an update.

Related errors


AI-assisted analysis of cjpais/Handy@ba10ce1943 (2026-08-17). Data as JSON: /api/errors/710a6880c392bed6. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/src/managers/transcription.rs:1352

                        };

                        debug!(
                            "transcribe-cpp run: task={:?}, language={:?}, initial_prompt={}",
                            run_options.task,
                            run_options.language,
                            run_options.family.is_some()
                        );

                        session
                            .run(&audio, &run_options)
                            .map(|t| {
                                // Whisper's audio-based LID (auto mode only;
                                // `None` when a language hint was passed).
                                model_detected_language = t.language;
                                t.text
                            })
                            .map_err(|e| {
                                anyhow::anyhow!("transcribe-cpp transcription failed: {}", e)
                            })
                    }
                    LoadedEngine::Parakeet(parakeet_engine) => {
                        let params = ParakeetParams {
                            timestamp_granularity: Some(TimestampGranularity::Segment),
                            ..Default::default()
                        };
                        parakeet_engine
                            .transcribe_with(&audio, &params)
                            .map(|r| r.text)
                            .map_err(|e| anyhow::anyhow!("Parakeet transcription failed: {}", e))
                    }
                    LoadedEngine::Moonshine(moonshine_engine) => moonshine_engine
                        .transcribe(&audio, &TranscribeOptions::default())
                        .map(|r| r.text)
                        .map_err(|e| anyhow::anyhow!("Moonshine transcription failed: {}", e)),
                    LoadedEngine::MoonshineStreaming(streaming_engine) => streaming_engine
                        .transcribe(&audio, &TranscribeOptions::default())

View on GitHub (pinned to ba10ce1943)