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

  1. Install/enable the TTS backend the service expects (e.g. edge-tts) and restart the service
  2. Check TTS configuration (endpoint, voice list) and network reachability, then restart so availability is re-evaluated
  3. Frontend should treat 503 as 'feature off' and hide/disable the speak button
  4. 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

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


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/ad932a60c966a47f. Report an issue: GitHub.