HKUDS/DeepTutor · error · VoiceProviderError
No endpoint URL configured for this provider.
Error message
No endpoint URL configured for this provider.
What it means
join_audio_path(base_url, suffix) builds an audio endpoint URL from an API base. If base_url is empty or whitespace, it cannot construct a URL and raises VoiceProviderError. Full URLs already containing "/audio/" are passed through verbatim with the query string preserved (e.g. Azure-style endpoints).
Source
Thrown at deeptutor/services/voice/base.py:96
Chrome's ``MediaRecorder.mimeType`` is typically ``audio/webm;codecs=opus``.
OpenAI-compatible transcription endpoints treat the codec parameter as an
unknown format and return 400 (``Unsupported file format: ...``). Keep the
type/subtype only.
"""
media_type = (content_type or "").split(";", 1)[0].strip()
return media_type or "application/octet-stream"
def join_audio_path(base_url: str, suffix: str) -> str:
"""Append an OpenAI audio path to a configured base URL.
``base_url`` is the API base (e.g. ``https://api.openai.com/v1``). If the
admin already pasted a full ``.../audio/...`` endpoint (some gateways /
Azure deployments), it is used verbatim and the query string preserved.
"""
base = (base_url or "").strip()
if not base:
raise VoiceProviderError("No endpoint URL configured for this provider.")
head, sep, query = base.partition("?")
if "/audio/" in head:
return base
joined = f"{head.rstrip('/')}/{suffix.lstrip('/')}"
return f"{joined}?{query}" if sep else joined
# Content blocks that should never be spoken aloud, stripped before synthesis.
_FENCED_CODE = re.compile(r"```.*?```", re.DOTALL)
_INLINE_CODE = re.compile(r"`([^`]*)`")
_IMAGE = re.compile(r"!\[[^\]]*\]\([^)]*\)")
_LINK = re.compile(r"\[([^\]]+)\]\([^)]*\)")
_HEADING = re.compile(r"^\s{0,3}#{1,6}\s*", re.MULTILINE)
_BLOCKQUOTE = re.compile(r"^\s{0,3}>\s?", re.MULTILINE)
_LIST_MARKER = re.compile(r"^\s{0,3}(?:[-*+]|\d+[.)])\s+", re.MULTILINE)
_EMPHASIS = re.compile(r"(\*{1,3}|_{1,3}|~~)(\S.*?\S|\S)\1")
_HTML_TAG = re.compile(r"<[^>]+>")
_TABLE_PIPE = re.compile(r"^\s*\|.*\|\s*$", re.MULTILINE)View on GitHub (pinned to 3e82f13042)
Solutions
- Set the provider base_url (e.g. https://api.openai.com/v1) in voice settings
- If you already have a full .../audio/... endpoint (Azure), pass it as base_url — it is used verbatim
- Validate voice config at startup; any enabled provider must have a non-empty endpoint
Example fix
// before
url = join_audio_path("", "audio/speech")
// after
url = join_audio_path("https://api.openai.com/v1", "audio/speech") Defensive patterns
Strategy: validation
Validate before calling
from deeptutor.services.voice.base import join_audio_path
base = (config.base_url or "").strip()
if not base:
raise ValueError("Voice provider endpoint (base_url) is required")
url = join_audio_path(base, "audio/speech") Type guard
def has_voice_endpoint(config) -> bool:
return bool((getattr(config, "base_url", None) or "").strip()) Try / catch
try:
url = join_audio_path(config.base_url, suffix)
except VoiceProviderError as exc:
if "No endpoint URL" in str(exc):
raise ConfigurationError("voice provider missing base_url") from exc
raise Prevention
- Pass full /audio/... URLs verbatim for Azure-style deployments
- Validate endpoints at settings-save time
- Never construct voice configs from partial env vars without defaults
When it happens
Trigger: Calling synthesize or transcribe (or the tested helper directly) with an empty base_url — the shared guard used by both TTS and STT URL construction.
Common situations: Missing voice provider endpoint in settings, env override blanking the value, or passing None from a config that was never populated for the selected provider.
Related errors
- No endpoint URL configured for this provider.
- No endpoint URL configured for TTS.
- {action} failed with HTTP {status_code}: {detail}
- No endpoint URL configured for STT.
- Unsupported STT adapter: {name!r}
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/f2f559dea35f72b2.
Report an issue: GitHub.