From def3483032d6e7282031cbd1ec1babd13f93b7ce Mon Sep 17 00:00:00 2001 From: Afonso Coutinho Date: Sat, 11 Jul 2026 03:19:51 +0100 Subject: [PATCH] fix: TTS available crashes on non-string tts_provider (#2034) --- services/tts/tts_service.py | 2 +- tests/test_tts_available_nonstring_provider.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/test_tts_available_nonstring_provider.py diff --git a/services/tts/tts_service.py b/services/tts/tts_service.py index e724434cb..2120d7720 100644 --- a/services/tts/tts_service.py +++ b/services/tts/tts_service.py @@ -68,7 +68,7 @@ class TTSService: if provider == "local": kokoro = self._get_kokoro() return kokoro is not None and kokoro.available - if provider.startswith("endpoint:"): + if isinstance(provider, str) and provider.startswith("endpoint:"): return True # assume reachable; errors surface at synthesis time return False diff --git a/tests/test_tts_available_nonstring_provider.py b/tests/test_tts_available_nonstring_provider.py new file mode 100644 index 000000000..632e1cd89 --- /dev/null +++ b/tests/test_tts_available_nonstring_provider.py @@ -0,0 +1,17 @@ +from services.tts.tts_service import TTSService + + +def test_available_tolerates_non_string_provider(tmp_path): + """A hand-edited/corrupt data/settings.json can store a non-string + tts_provider (e.g. null or a number). available reads it and calls + provider.startswith("endpoint:"), which raised AttributeError on a + non-str. It must instead fall through and report unavailable.""" + service = TTSService(cache_dir=str(tmp_path)) + service._load_settings = lambda: { + "tts_enabled": True, + "tts_provider": 123, + "tts_model": "tts-1", + "tts_voice": "alloy", + "tts_speed": "1", + } + assert service.available is False