tinyhumansai/openhuman · error · anyhow::Error

voice provider '{slug}' has no API credential configured

Error message

voice provider '{slug}' has no API credential configured

What it means

voice_status constructs the configured STT provider as a probe and that construction failed for a third-party slug because no matching API credential exists in voice_providers; the status call reports the engine as unavailable for exactly this reason.

Source

Thrown at src/openhuman/voice/ops.rs:50

    // resolves to a provider: the backend proxy always does, a third-party slug
    // only when its `voice_providers` entry exists. Constructing the provider is
    // the same check the transcribe path performs, and it makes no network call
    // — so this reports the real failure a user would hit, not a guess.
    let stt_engine = effective_stt_provider(config);
    let stt_error = create_stt_provider(&stt_engine, "", config)
        .and_then(|_| {
            let slug = stt_engine
                .split_once(':')
                .map_or(stt_engine.as_str(), |(slug, _)| slug);
            if matches!(slug.trim(), "cloud" | "openhuman" | "backend") {
                return Ok(());
            }
            let key = crate::openhuman::inference::provider::factory::lookup_key_for_slug(
                slug.trim(),
                config,
            )?;
            if key.trim().is_empty() {
                anyhow::bail!("voice provider '{slug}' has no API credential configured")
            }
            Ok(())
        })
        .err()
        .map(|e| e.to_string());
    let stt_available = stt_error.is_none();
    let tts_available = piper_bin.is_some() && tts_voice.is_some();

    debug!(
        "{LOG_PREFIX} stt_available={stt_available} stt_engine={stt_engine} \
         tts_available={tts_available} piper_bin={} tts_voice={} stt_error={:?}",
        safe_basename_path(&piper_bin),
        safe_basename_str(&tts_voice),
        stt_error,
    );

    let tts_provider = if config.local_ai.tts_provider.trim().is_empty() {
        "cloud".to_string()

View on GitHub (pinned to 7491200858)

Solutions

  1. Configure credentials for the provider in the voice_providers config section
  2. Switch voice_server.stt_engine to 'backend' to use the backend proxy
  3. Set a valid stt_provider routing string if the slug is stale
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/openhuman/voice/ops.rs:50 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/502779f9d1aac9fd. Report an issue: GitHub.