{"record":{"id":"2b5c1f7f94840ae3","repo":"zeroclaw-labs/zeroclaw","slug":"google-stt-does-not-support-ext-input","errorCode":null,"errorMessage":"Google STT does not support '.{ext}' input","messagePattern":"Google STT does not support '\\.(.+?)' input","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/zeroclaw-channels/src/transcription.rs","lineNumber":704,"sourceCode":"            .into_iter()\n            .map(String::from)\n            .collect()\n    }\n\n    async fn transcribe(&self, audio_data: &[u8], file_name: &str) -> Result<String> {\n        let (normalized_name, _) = validate_audio(audio_data, file_name)?;\n\n        let encoding = match normalized_name\n            .rsplit_once('.')\n            .map(|(_, e)| e.to_ascii_lowercase())\n            .as_deref()\n        {\n            Some(\"flac\") => \"FLAC\",\n            Some(\"wav\") => \"LINEAR16\",\n            Some(\"ogg\" | \"opus\") => \"OGG_OPUS\",\n            Some(\"mp3\") => \"MP3\",\n            Some(\"webm\") => \"WEBM_OPUS\",\n            Some(ext) => bail!(\"Google STT does not support '.{ext}' input\"),\n            None => bail!(\"Google STT requires a file extension\"),\n        };\n\n        let audio_content =\n            base64::Engine::encode(&base64::engine::general_purpose::STANDARD, audio_data);\n\n        let request_body = serde_json::json!({\n            \"config\": {\n                \"encoding\": encoding,\n                \"languageCode\": &self.language_code,\n                \"enableAutomaticPunctuation\": true,\n            },\n            \"audio\": {\n                \"content\": audio_content,\n            }\n        });\n\n        let resp = self","sourceCodeStart":686,"sourceCodeEnd":722,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/transcription.rs#L686-L722","documentation":"GoogleSttProvider::transcribe() maps the file extension to a Google Speech-to-Text encoding enum and only accepts flac, wav, ogg, opus, mp3, and webm. Any other extension bails before any API call. Note the gap versus the shared validate_audio(): formats like m4a/mp4/mpga pass the 25 MB/format gate (mime_for_audio accepts them for Whisper-compatible APIs) but Google's provider rejects them right after.","triggerScenarios":"transcribe() on the google provider with a file_name whose extension is not flac/wav/ogg/opus/mp3/webm — most commonly .m4a (iPhone voice memos), .mp4, .mpga, or .aac. The error message names the exact rejected extension.","commonSituations":"iPhone/Android voice notes recorded as .m4a routed to the google provider while other formats work fine; switching a working Groq/OpenAI setup to Google and suddenly m4a inputs fail; users sending audio as video-less .mp4 containers.","solutions":["Route m4a/mp4/mpga inputs to a provider that accepts them (groq, openai) — set the agent's transcription_provider accordingly","Convert the audio before transcribing: ffmpeg -i in.m4a -ar 16000 -ac 1 out.flac","Add a per-extension provider selection at the channel layer so Google only receives its supported formats"],"exampleFix":"// before: .m4a sent to google provider -> error\nlet text = manager.transcribe_with_provider(&audio, \"memo.m4a\", \"google\").await?;\n\n// after: convert first\nlet flac = transcode_to_flac(&audio)?;\nlet text = manager.transcribe_with_provider(&flac, \"memo.flac\", \"google\").await?;","handlingStrategy":"validation","validationCode":"const GOOGLE_STT_EXTS: &[&str] = &[\"flac\", \"wav\", \"ogg\", \"opus\", \"mp3\", \"webm\"];\n\nfn google_stt_accepts(file_name: &str) -> bool {\n    file_name.rsplit_once('.').map(|(_, e)| e.to_ascii_lowercase())\n        .is_some_and(|e| GOOGLE_STT_EXTS.contains(&e.as_str()))\n}","typeGuard":"fn google_stt_accepts(file_name: &str) -> bool {\n    let ext = file_name.rsplit_once('.')\n        .map(|(_, e)| e.to_ascii_lowercase())\n        .unwrap_or_default();\n    matches!(ext.as_str(), \"flac\" | \"wav\" | \"ogg\" | \"opus\" | \"mp3\" | \"webm\")\n}","tryCatchPattern":null,"preventionTips":["Remember m4a/mp4/mpga pass the shared format check but Google rejects them — validate against Google's own list before dispatching","Route by extension: m4a -> groq/openai, flac/wav -> any provider","Convert at ingest with ffmpeg to flac for a format every provider accepts"],"tags":["google","stt","unsupported-format","transcription","pre-flight-check"],"backgroundTag":"unsupported-file-format","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}