odysseus-dev/odysseus · error · HTTPException

STT service not available or set to browser mode

Error message

STT service not available or set to browser mode

What it means

503 from POST /api/stt/transcribe: stt_service.available is false, meaning the server has no server-side speech-to-text backend — either no provider is configured (no local Whisper, no API endpoint) or STT is deliberately set to browser mode, where transcription happens in the client and this endpoint is not the right path.

Source

Thrown at routes/stt_routes.py:30

def setup_stt_routes(stt_service):
    """Setup STT routes with the provided STT service"""
    router = APIRouter(prefix="/api/stt", tags=["stt"])

    @router.get("/stats")
    async def get_stt_stats():
        """Get STT service statistics"""
        try:
            return stt_service.get_stats()
        except Exception as e:
            logger.error(f"Failed to get STT stats: {e}")
            raise HTTPException(status_code=500, detail=str(e))

    @router.post("/transcribe")
    async def transcribe_audio(file: UploadFile = File(...)):
        """Transcribe uploaded audio file to text"""
        try:
            if not stt_service.available:
                raise HTTPException(
                    status_code=503,
                    detail={"message": "STT service not available or set to browser mode"}
                )

            audio_bytes = await read_upload_limited(file, STT_MAX_AUDIO_BYTES, "Audio file")
            if not audio_bytes:
                raise HTTPException(status_code=400, detail={"message": "Empty audio file"})

            text = stt_service.transcribe(audio_bytes)
            if text is None:
                raise HTTPException(
                    status_code=500,
                    detail={"message": "Transcription failed"}
                )

            return {"text": text}

        except HTTPException:

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. If browser mode is intended, use the browser STT path client-side and stop calling /transcribe.
  2. To use server-side STT, configure a provider (local Whisper model or API endpoint) and restart so stt_service.available becomes true.
  3. Check GET /api/stt/stats to see availability and provider state before sending audio.
  4. Verify the STT dependency installed and the model downloaded (first-run downloads need network).

Example fix

# before
r = client.post("/api/stt/transcribe", files={"file": audio})  # 503
r.raise_for_status()

# after
stats = client.get("/api/stt/stats").json()
if not stats.get("available"):
    transcript = browser_webspeech_transcribe(audio)  # or configure server STT
else:
    r = client.post("/api/stt/transcribe", files={"file": audio})
    r.raise_for_status()
    transcript = r.json()["text"]
Defensive patterns

Strategy: type-guard

Validate before calling

stats = client.get(f"{base}/api/stt/stats").json()
if not stats.get("available"):
    raise ServiceUnavailable("server STT off/browser mode — configure a provider or use browser STT")

Type guard

def stt_ready(stt_service) -> bool:
    """True when the server can transcribe uploads right now."""
    return bool(getattr(stt_service, "available", False))

Try / catch

r = client.post(f"{base}/api/stt/transcribe", files={"file": f})
if r.status_code == 503:
    transcript = browser_fallback_stt(audio_source)  # or prompt admin to configure server STT
else:
    r.raise_for_status()
    transcript = r.json()["text"]

Prevention

When it happens

Trigger: POST /transcribe on a server whose STT config is 'browser'; a deployment where the Whisper model/dependency was never installed; the STT provider failed to initialize at startup (model load failure) leaving available=False.

Common situations: Default install with browser-based WebSpeech STT expected but the client calls the REST endpoint anyway; missing whisper/faster-whisper dependency or model download blocked; STT provider credentials absent.

Related errors


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