{"record":{"id":"9f722bf5d863196e","repo":"mastra-ai/mastra","slug":"voicecredentialerror-entry-provider","errorCode":null,"errorMessage":"VoiceCredentialError(entry.provider)","messagePattern":"VoiceCredentialError\\(entry\\.provider\\)","errorType":"exception","errorClass":"VoiceCredentialError","httpStatus":null,"severity":"error","filePath":"mastracode/tui/src/tui/voice/transcribe.ts","lineNumber":116,"sourceCode":"}\n\nexport interface TranscribeOptions {\n  /** STT provider id (see `stt-registry.ts`). Defaults to the registry default. */\n  provider?: string;\n  /** Model id within the provider. Defaults to the provider's default model. */\n  model?: string;\n  authStorage?: AuthStorage;\n}\n\n/**\n * Transcribe recorded WAV audio to text via the configured cloud provider.\n * Throws VoiceCredentialError if no API key is available for the provider.\n */\nexport async function transcribeAudio(audio: Buffer, options: TranscribeOptions = {}): Promise<string> {\n  const entry = resolveSTTModel(options.provider, options.model) ?? DEFAULT_STT_MODEL;\n  const apiKey = resolveProviderApiKey(entry.provider, options.authStorage);\n  if (!apiKey) {\n    throw new VoiceCredentialError(entry.provider);\n  }\n\n  const voice = buildVoice(entry, apiKey);\n  const result = await voice.listen(Readable.from(audio), { filetype: 'wav' });\n  return normalizeTranscript(result);\n}\n\n/**\n * A reusable transcriber bound to one provider/model. Building the underlying\n * `MastraVoice` client once and reusing it across calls lets the HTTP client\n * keep its connection to the provider warm (keep-alive), which removes the\n * DNS + TLS handshake cost from every live-partial tick — the main reason the\n * first dictation streams in slowly while later ones feel instant.\n */\nexport interface ReusableTranscriber {\n  transcribe(audio: Buffer): Promise<string>;\n}\n","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/tui/src/tui/voice/transcribe.ts#L98-L134","documentation":"transcribeAudio resolves an STT model entry for the requested provider, then looks up an API key for that provider (via options.authStorage or default credential resolution). If no key can be resolved it throws VoiceCredentialError(entry.provider). The library refuses to attempt transcription because the upstream speech-to-text API would reject unauthenticated requests.","triggerScenarios":"Calling transcribeAudio(audio, { provider }) where resolveProviderApiKey(entry.provider, authStorage) returns undefined — the provider's API key is absent from auth storage, environment, or the authStorage passed in options; or the provider name resolves to an entry whose credentials were never configured.","commonSituations":"Fresh machine without a saved provider API key, missing environment variable for the chosen STT provider, authStorage file not yet populated via login, or a typo'd provider/model name resolving to a provider with no stored credentials.","solutions":["Obtain and save an API key for the resolved provider (e.g. via the TUI's auth/login flow or the auth storage file)","Set the provider's API key environment variable the resolver checks","Pass a populated authStorage object in TranscribeOptions for this call","Check the provider/model option spelling resolves to the intended entry","Fall back to a provider whose credentials are already configured"],"exampleFix":"// before\nawait transcribeAudio(audio, { provider: 'openai' }); // no key configured\n// after\nconst apiKey = resolveProviderApiKey('openai', authStorage);\nif (!apiKey) await saveProviderKey('openai', process.env.OPENAI_API_KEY);\nawait transcribeAudio(audio, { provider: 'openai', authStorage });","handlingStrategy":"validation","validationCode":"const apiKey = resolveProviderApiKey(provider, authStorage);\nif (!apiKey) throw new Error(`No API key configured for STT provider '${provider}'. Save a key before transcribing.`);","typeGuard":null,"tryCatchPattern":"try {\n  const text = await transcribeAudio(audio, { provider });\n} catch (e) {\n  if (e instanceof VoiceCredentialError) {\n    // prompt user to configure credentials for e.provider\n  }\n}","preventionTips":["Run a startup credential check for the configured voice providers","Keep provider keys in one well-known auth storage file","Validate provider/model option spellings before calling","Surface a UI prompt to save missing keys instead of failing mid-session"],"tags":["credentials","authentication","voice","api-key"],"backgroundTag":"missing-api-key","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}