mastra-ai/mastra · error · VoiceCredentialError

VoiceCredentialError(entry.provider)

Error message

VoiceCredentialError(entry.provider)

What it means

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.

Source

Thrown at mastracode/tui/src/tui/voice/transcribe.ts:116

}

export interface TranscribeOptions {
  /** STT provider id (see `stt-registry.ts`). Defaults to the registry default. */
  provider?: string;
  /** Model id within the provider. Defaults to the provider's default model. */
  model?: string;
  authStorage?: AuthStorage;
}

/**
 * Transcribe recorded WAV audio to text via the configured cloud provider.
 * Throws VoiceCredentialError if no API key is available for the provider.
 */
export async function transcribeAudio(audio: Buffer, options: TranscribeOptions = {}): Promise<string> {
  const entry = resolveSTTModel(options.provider, options.model) ?? DEFAULT_STT_MODEL;
  const apiKey = resolveProviderApiKey(entry.provider, options.authStorage);
  if (!apiKey) {
    throw new VoiceCredentialError(entry.provider);
  }

  const voice = buildVoice(entry, apiKey);
  const result = await voice.listen(Readable.from(audio), { filetype: 'wav' });
  return normalizeTranscript(result);
}

/**
 * A reusable transcriber bound to one provider/model. Building the underlying
 * `MastraVoice` client once and reusing it across calls lets the HTTP client
 * keep its connection to the provider warm (keep-alive), which removes the
 * DNS + TLS handshake cost from every live-partial tick — the main reason the
 * first dictation streams in slowly while later ones feel instant.
 */
export interface ReusableTranscriber {
  transcribe(audio: Buffer): Promise<string>;
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Obtain and save an API key for the resolved provider (e.g. via the TUI's auth/login flow or the auth storage file)
  2. Set the provider's API key environment variable the resolver checks
  3. Pass a populated authStorage object in TranscribeOptions for this call
  4. Check the provider/model option spelling resolves to the intended entry
  5. Fall back to a provider whose credentials are already configured

Example fix

// before
await transcribeAudio(audio, { provider: 'openai' }); // no key configured
// after
const apiKey = resolveProviderApiKey('openai', authStorage);
if (!apiKey) await saveProviderKey('openai', process.env.OPENAI_API_KEY);
await transcribeAudio(audio, { provider: 'openai', authStorage });
Defensive patterns

Strategy: validation

Validate before calling

const apiKey = resolveProviderApiKey(provider, authStorage);
if (!apiKey) throw new Error(`No API key configured for STT provider '${provider}'. Save a key before transcribing.`);

Try / catch

try {
  const text = await transcribeAudio(audio, { provider });
} catch (e) {
  if (e instanceof VoiceCredentialError) {
    // prompt user to configure credentials for e.provider
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/9f722bf5d863196e. Report an issue: GitHub.