{"record":{"id":"a96c15f9f43024df","repo":"aaif-goose/goose","slug":"unknown-model","errorCode":null,"errorMessage":"Unknown model: {}","messagePattern":"Unknown model: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose/src/dictation/providers.rs","lineNumber":145,"sourceCode":"        _ => {\n            let def = get_provider_def(provider);\n            config.get_secret::<String>(def.config_key).is_ok()\n        }\n    }\n}\n\n#[cfg(feature = \"local-inference\")]\npub async fn transcribe_local(audio_bytes: Vec<u8>) -> Result<String> {\n    tokio::task::spawn_blocking(move || {\n        let config = Config::global();\n        let model_id = config\n            .get(LOCAL_WHISPER_MODEL_CONFIG_KEY, false)\n            .ok()\n            .and_then(|v| v.as_str().map(|s| s.to_string()))\n            .ok_or_else(|| anyhow::anyhow!(\"Local Whisper model not configured\"))?;\n\n        let model = super::whisper::get_model(&model_id)\n            .ok_or_else(|| anyhow::anyhow!(\"Unknown model: {}\", model_id))?;\n        let model_path = model.local_path();\n\n        let mut transcriber_lock = LOCAL_TRANSCRIBER\n            .lock()\n            .map_err(|e| anyhow::anyhow!(\"Failed to lock transcriber: {}\", e))?;\n\n        let model_path_str = model_path.to_string_lossy().to_string();\n        let needs_reload = match transcriber_lock.as_ref() {\n            None => true,\n            Some((cached_path, _)) => cached_path != &model_path_str,\n        };\n\n        if needs_reload {\n            tracing::info!(\"Loading Whisper model from: {}\", model_path.display());\n\n            let transcriber = super::whisper::WhisperTranscriber::new_with_tokenizer(\n                &model_id,\n                &model_path,","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose/src/dictation/providers.rs#L127-L163","documentation":"transcribe_local resolves LOCAL_WHISPER_MODEL through whisper::get_model, which is an exact-match lookup over the static MODELS catalog containing only the ids \"tiny\", \"base\", \"small\", and \"medium\" (whisper.rs:61-79). Any other string returns None and becomes this error. Note the catalog is stricter than whisper's internal Config fallback, which would silently fall back to tiny for unknown ids.","triggerScenarios":"LOCAL_WHISPER_MODEL set to an unsupported value: \"large\", \"whisper-small\", \"small.en\", \"Small\" (case-sensitive), or a value with trailing whitespace.","commonSituations":"Copying a model name from OpenAI's API docs (large-v3, whisper-1) instead of goose's local ids; hand-editing the config file; case or whitespace mistakes.","solutions":["Set LOCAL_WHISPER_MODEL to exactly one of: tiny, base, small, medium","Pick programmatically with recommend_model() or list valid ids via available_models()"],"exampleFix":"# before\ngoose config set --params LOCAL_WHISPER_MODEL large-v3\n\n# after\ngoose config set --params LOCAL_WHISPER_MODEL small","handlingStrategy":"validation","validationCode":"use goose::dictation::whisper::{available_models, get_model};\n\nfn model_id_supported(id: &str) -> bool {\n    get_model(id).is_some()\n}\n\n// validate before transcribing, or offer the valid set:\nlet ids: Vec<&str> = available_models().iter().map(|m| m.id).collect();","typeGuard":"fn model_id_supported(id: &str) -> bool {\n    goose::dictation::whisper::get_model(id).is_some() // ids: tiny | base | small | medium\n}","tryCatchPattern":null,"preventionTips":["Restrict the config UI to a dropdown of available_models() ids","Trim whitespace and lowercase user input before storing it as LOCAL_WHISPER_MODEL","Do not copy model names from OpenAI docs — local ids are only tiny/base/small/medium"],"tags":["dictation","whisper","validation","config"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}