spacedriveapp/spacedrive · error

Whisper model not found: {}. Please download it first.

Error message

Whisper model not found: {}. Please download it first.

What it means

Raised by transcribe_audio_file when the Whisper GGML model file (ggml-<model>.bin) is missing from the models directory resolved by get_whisper_models_dir(data_dir). Whisper needs the model binary loaded from disk before any inference can run, so transcription aborts before spawn_blocking. The path is built from the WhisperModel selector, so any variant whose weights were never fetched fails immediately.

Source

Thrown at core/src/ops/media/speech/mod.rs:45

#[cfg(feature = "speech-to-text")]
pub async fn transcribe_audio_file(
	source_path: &Path,
	model: &str,
	language: Option<&str>,
	data_dir: &Path,
) -> Result<String> {
	use tokio::task::spawn_blocking;

	let source = source_path.to_path_buf();
	let model_name = model.to_string();
	let lang = language.map(|s| s.to_string());

	// Get model path from data directory
	let model_path = crate::ops::models::get_whisper_models_dir(data_dir)
		.join(format!("ggml-{}.bin", model_name));

	if !model_path.exists() {
		anyhow::bail!(
			"Whisper model not found: {}. Please download it first.",
			model_path.display()
		);
	}

	// Run whisper in blocking task (CPU/GPU intensive)
	spawn_blocking(move || {
		use whisper_rs::{FullParams, SamplingStrategy, WhisperContext, WhisperContextParameters};

		// Load model
		let ctx = WhisperContext::new_with_params(
			model_path.to_str().context("Invalid model path")?,
			WhisperContextParameters::default(),
		)
		.context("Failed to load Whisper model")?;

		// Load and convert audio to 16kHz mono f32 samples
		let audio_data = load_audio_samples(&source)?;

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Before transcribing, ensure the model exists: call ensure_whisper_model(ctx, model, &data_dir) (core/src/ops/models/ensure.rs) or dispatch ModelDownloadJob::for_whisper_model and wait for completion.
  2. Verify the exact expected file: get_whisper_models_dir(&data_dir).join(format!("ggml-{}.bin", model_name)) exists and is non-trivial in size.
  3. Confirm the daemon's data dir matches the one the models were downloaded into (default_data_dir vs configured path), especially with daemon/CLI user mismatch.
  4. Re-download via the models download action if the file is truncated (compare against model.size_bytes()).

Example fix

// before
let srt = transcribe_audio_file(&entry.path, &self.model, None, &data_dir).await?;

// after
ensure_whisper_model(ctx, self.model.clone(), &data_dir).await?;
let srt = transcribe_audio_file(&entry.path, &self.model, None, &data_dir).await?;
Defensive patterns

Strategy: validation

Validate before calling

use crate::ops::models::{get_whisper_models_dir, whisper::WhisperModel};

fn whisper_model_ready(data_dir: &std::path::Path, model: &WhisperModel) -> bool {
	get_whisper_models_dir(data_dir)
		.join(format!("ggml-{}.bin", model))
		.exists()
}

Type guard

fn is_missing_whisper_model(err: &anyhow::Error) -> bool {
	err.to_string().starts_with("Whisper model not found")
}

Try / catch

match transcribe_audio_file(&path, &model, lang, &data_dir).await {
	Err(e) if is_missing_whisper_model(&e) => // prompt user / dispatch model download, do not retry now
	Err(e) => return Err(e),
	Ok(srt) => /* proceed */
}

Prevention

When it happens

Trigger: Running the speech_to_text processor or calling transcribe_audio_file with a WhisperModel (e.g. Medium) whose ggml-medium.bin was never downloaded; enabling transcription on a fresh install; switching model size in settings without downloading the new weights; deleting the models directory under the data dir.

Common situations: Fresh installs where transcription started before the ModelDownloadJob finished; data dir moved or wiped; daemon running under a different user/home than the one that downloaded models; interrupted downloads leaving a truncated file that later gets cleaned up.

Related errors


AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16). Data as JSON: /api/errors/b852f2e60d391a0a. Report an issue: GitHub.