HKUDS/DeepTutor · error · VoiceProviderError

No endpoint URL configured for this provider.

Error message

No endpoint URL configured for this provider.

What it means

_join_api_path builds an OpenRouter chat/completions URL from the provider base_url. An empty or whitespace-only base_url means no endpoint is configured, so the adapter refuses to construct a URL and raises VoiceProviderError. This is a configuration error surfaced before any network call.

Source

Thrown at deeptutor/services/voice/adapters/openai_compat.py:80


def _raise_for_provider(resp: httpx.Response, action: str) -> None:
    """Surface a provider error with a trimmed body for diagnostics."""
    if resp.status_code < 400:
        return
    body = resp.text or ""
    raise VoiceProviderHTTPError(
        _provider_error_message(action, resp.status_code, body),
        status_code=resp.status_code,
        body=body,
    )


def _join_api_path(base_url: str, suffix: str) -> str:
    """Append a generic API path to ``base_url`` while preserving query strings."""
    base = (base_url or "").strip()
    if not base:
        raise VoiceProviderError("No endpoint URL configured for this provider.")
    head, sep, query = base.partition("?")
    suffix = suffix.strip("/")
    if head.rstrip("/").endswith(f"/{suffix}"):
        return base
    joined = f"{head.rstrip('/')}/{suffix}"
    return f"{joined}?{query}" if sep else joined


def _chat_audio_format(response_format: str) -> str:
    """Map OpenAI speech formats onto OpenRouter chat audio formats."""
    fmt = (response_format or "mp3").strip().lower()
    return "pcm16" if fmt == "pcm" else fmt


def _openrouter_tts_hint(config: TTSConfig) -> str:
    """Return a provider/model-specific hint for opaque OpenRouter TTS errors."""
    model = (config.model or "").lower()
    voice = (config.voice or "").strip()

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Set the provider's base_url in voice settings (e.g. https://openrouter.ai/api/v1)
  2. Verify runtime settings/env overrides are not blanking the field (data/user/settings/*.json)
  3. Fail fast at app startup by validating that any enabled voice provider has a base URL

Example fix

// before
config.base_url = ""
// after
config.base_url = "https://openrouter.ai/api/v1"
Defensive patterns

Strategy: validation

Validate before calling

if not (config.base_url or "").strip():
    raise ValueError("OpenRouter TTS base_url is required before synthesis")

Try / catch

try:
    audio, ct = await adapter.synthesize(text, config)
except VoiceProviderError as exc:
    if "No endpoint URL" in str(exc):
        log.error("Voice provider misconfigured: missing base_url")
    raise

Prevention

When it happens

Trigger: _synthesize_chat_audio is reached (OpenRouter TTS fallback after /audio/speech fails) while config.base_url is empty, None, or only whitespace.

Common situations: Voice settings JSON omits the base URL for the OpenRouter provider, the env override was cleared, or a provider profile was created without an endpoint because the user relied on a default that only exists for OpenAI-style keys.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/ca074a131afe361c. Report an issue: GitHub.