odysseus-dev/odysseus · warning · HTTPException
TTS service not available
Error message
TTS service not available
What it means
HTTP 503 from POST /api/tts/synthesize when tts_service.available is false — the service detected at startup that no usable TTS backend exists. This capability flag is checked before any synthesis attempt, so the request never reaches the engine.
Source
Thrown at routes/tts_routes.py:35
def setup_tts_routes(tts_service):
"""Setup TTS routes with the provided TTS service"""
router = APIRouter(prefix="/api/tts", tags=["tts"])
@router.get("/stats")
async def get_tts_stats():
"""Get TTS service statistics"""
try:
return tts_service.get_stats()
except Exception as e:
logger.error(f"Failed to get TTS stats: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/synthesize")
async def synthesize_speech(request: TTSRequest):
"""Synthesize speech from text"""
try:
if not tts_service.available:
raise HTTPException(
status_code=503,
detail={"message": "TTS service not available"}
)
if request.format == "base64":
audio_b64 = tts_service.synthesize_to_base64(request.text)
if not audio_b64:
raise HTTPException(
status_code=500,
detail={"message": "Synthesis failed"}
)
return {"audio": audio_b64}
else: # audio format
audio_data = tts_service.synthesize(request.text)
if not audio_data:
raise HTTPException(
status_code=500,View on GitHub (pinned to f9235ebbf1)
Solutions
- Install/enable the TTS backend the service expects (e.g. edge-tts) and restart the service
- Check TTS configuration (endpoint, voice list) and network reachability, then restart so availability is re-evaluated
- Frontend should treat 503 as 'feature off' and hide/disable the speak button
- Verify via GET /api/tts/stats whether the service reports itself available before retrying synthesis
Defensive patterns
Strategy: type-guard
Validate before calling
const stats = await getTtsStats();
if (!stats?.available) throw new Error('TTS disabled on this server'); Type guard
function ttsAvailable(s: unknown): s is { available: true } {
return !!s && (s as any).available === true;
} Try / catch
if (resp.status === 503) { hideSpeakButtons(); return; } // permanent condition, do not retry Prevention
- Query /api/tts/stats before showing TTS controls
- Treat 503 as configuration, not transient — retrying will not help
When it happens
Trigger: POST /api/tts/synthesize on an instance whose TTS backend failed init: dependency not installed, provider unreachable at startup, or the feature disabled in config.
Common situations: Container/image built without TTS dependencies; offline environment where the cloud TTS engine could not be reached during init; feature intentionally disabled so available stays False.
Related errors
- str(e)
- Invalid remote_host — must be host or user@host, no SSH opti
- Invalid ssh_port
- Unknown wipe kind: {kind!r}
- Not found
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/ad932a60c966a47f.
Report an issue: GitHub.