{"record":{"id":"58e6489d9ad18afc","repo":"zeroclaw-labs/zeroclaw","slug":"agent-has-no-transcription-provider-configured-se","errorCode":null,"errorMessage":"Agent has no transcription_provider configured. Set `agent.<alias>.transcription_provider = \"<type>.<alias>\"` referencing a configured transcription provider.","messagePattern":"Agent has no transcription_provider configured\\. Set `agent\\.<alias>\\.transcription_provider = \"<type>\\.<alias>\"` referencing a configured transcription provider\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/transcription.rs","lineNumber":1128,"sourceCode":"        self\n    }\n\n    /// Set the resolved agent `transcription_provider` alias. Called by\n    /// orchestrators that bind this manager to a specific agent at startup.\n    /// Subsequent `transcribe` calls dispatch to this alias.\n    #[must_use]\n    pub fn with_agent_transcription_provider(mut self, alias: impl Into<String>) -> Self {\n        self.agent_transcription_provider = alias.into();\n        self\n    }\n\n    /// Transcribe audio using the runtime-active agent's resolved\n    /// `transcription_provider`. Fails loud when the agent has no\n    /// transcription_provider configured — there is no global default.\n    pub async fn transcribe(&self, audio_data: &[u8], file_name: &str) -> Result<String> {\n        let provider_alias = self.agent_transcription_provider.as_str();\n        if provider_alias.is_empty() {\n            bail!(\n                \"Agent has no transcription_provider configured. Set \\\n                 `agent.<alias>.transcription_provider = \\\"<type>.<alias>\\\"` \\\n                 referencing a configured transcription provider.\"\n            );\n        }\n        self.transcribe_with_provider(audio_data, file_name, provider_alias)\n            .await\n    }\n\n    /// Transcribe audio using a specific named transcription_provider.\n    pub async fn transcribe_with_provider(\n        &self,\n        audio_data: &[u8],\n        file_name: &str,\n        transcription_provider: &str,\n    ) -> Result<String> {\n        let p = self.transcription_providers.get(transcription_provider).ok_or_else(|| {\n            let available: Vec<&str> = self.transcription_providers.keys().map(|k| k.as_str()).collect();","sourceCodeStart":1110,"sourceCodeEnd":1146,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/transcription.rs#L1110-L1146","documentation":"TranscriptionManager::transcribe() dispatches to the agent-resolved provider alias stored in agent_transcription_provider, and that alias is empty. There is deliberately no global default: from_config_for_agent() resolves it from agent.<alias>.transcription_provider, and an unset/missing agent or empty field leaves it empty. The manager also exposes transcribe_with_provider() to bypass the agent binding explicitly.","triggerScenarios":"transcribe() called when the resolved agent alias is empty: the runtime agent alias is not set or not found in [agents], the agent block exists but transcription_provider is unset/empty, or the manager was built via new()/empty() and nobody called with_agent_transcription_provider().","commonSituations":"Agent defined in config with a provider block configured globally but the per-agent transcription_provider key forgotten; default agent alias resolution returning a name absent from [agents]; orchestrator constructing the manager with new() and forgetting to bind the agent's provider.","solutions":["Set the per-agent key: agent.<alias>.transcription_provider = \"groq\" (legacy name) or \"<type>.<alias>\" (typed, e.g. \"openai.main\")","Verify the agent alias actually exists in [agents] — a typo means resolution silently yields empty","In code that cannot rely on agent binding, call transcribe_with_provider(&audio, name, alias) with a name from available_providers()"],"exampleFix":"# before\n[transcription]\nenabled = true\napi_key = \"gsk_...\"\napi_url = \"https://api.groq.com/openai/v1/audio/transcriptions\"\n\n[agents.main]\n# no transcription_provider -> transcribe() errors\n\n# after\n[agents.main]\ntranscription_provider = \"groq\"","handlingStrategy":"validation","validationCode":"// At startup, verify the agent binding before serving traffic\nfn agent_provider_configured(cfg: &Config, alias: &str) -> bool {\n    cfg.agents.get(alias)\n        .map(|a| !a.transcription_provider.is_empty())\n        .unwrap_or(false)\n}","typeGuard":"fn agent_provider_configured(cfg: &Config, alias: &str) -> bool {\n    cfg.agents.get(alias)\n        .map(|a| !a.transcription_provider.is_empty())\n        .unwrap_or(false)\n}","tryCatchPattern":"match manager.transcribe(&audio, name).await {\n    Ok(text) => Some(text),\n    Err(e) if e.to_string().contains(\"no transcription_provider configured\") => {\n        tracing::error!(\"agent transcription_provider not set; configure agent.<alias>.transcription_provider\");\n        None // or fall back to transcribe_with_provider with a known alias\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Set agent.<alias>.transcription_provider for every agent that can receive voice notes","Assert at startup that the resolved alias exists in [agents] and its provider is in available_providers()","Remember there is no global default — enabling a provider block alone is not enough"],"tags":["config","transcription","agent","missing-provider"],"backgroundTag":"config-validation-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}