[TTS] Improve voice delete error message (#7795)

Signed-off-by: Clodagh Walsh <clodaghwalsh17@gmail.com>
This commit is contained in:
Clodagh Walsh authored and GitHub committed 2026-09-28 09:42:34 -04:00
1 parent 5ce6f5dc49
commit 9c688aeba0
4 files changed
+84 -23

No files matched your search

@@ -38,6 +38,7 @@ from vllm_omni.entrypoints.omni_base import OmniEngineDeadError
from vllm_omni.entrypoints.openai import api_server as api_server_module
from vllm_omni.entrypoints.openai import serving_speech as serving_speech_module
from vllm_omni.entrypoints.openai.audio_utils_mixin import AudioMixin
from vllm_omni.entrypoints.openai.errors import InvalidPresetVoiceReferenceError, InvalidVoiceReferenceError
from vllm_omni.entrypoints.openai.protocol.audio import (
BatchSpeechRequest,
CreateAudio,
@@ -331,10 +332,12 @@ def test_app(mocker: MockerFixture, tmp_path, monkeypatch):
# Add delete_voice endpoint
async def delete_voice(name: str):
try:
success = await speech_server.delete_voice(name)
if not success:
raise HTTPException(status_code=404, detail=f"Voice '{name}' not found")
await speech_server.delete_voice(name)
return {"success": True, "message": f"Voice '{name}' deleted successfully"}
except InvalidPresetVoiceReferenceError as e:
raise HTTPException(status_code=403, detail=str(e))
except InvalidVoiceReferenceError as e:
raise HTTPException(status_code=404, detail=str(e))
except HTTPException:
raise
except ValueError as e:
@@ -593,7 +596,8 @@ class TestSpeechAPI:
def test_upload_voice_with_speaker_description(self, client, tmp_path):
"""Test voice upload with speaker_description stores and returns the description."""
# Pre-cleanup in case a previous test run left this voice behind
client.delete("/v1/audio/voices/test_voice_vd")
response = client.delete("/v1/audio/voices/test_voice_vd")
assert response.status_code == 404 or response.status_code == 200
audio_content = b"fake audio content" * 1000
files = {"audio_sample": ("test.wav", audio_content, "audio/wav")}
@@ -611,7 +615,9 @@ class TestSpeechAPI:
def test_upload_voice_speaker_description_in_listing(self, client):
"""Test that speaker_description survives the upload → list round-trip."""
client.delete("/v1/audio/voices/test_voice_sd_list")
# Pre-cleanup in case a previous test run left this voice behind
response = client.delete("/v1/audio/voices/test_voice_sd_list")
assert response.status_code == 404 or response.status_code == 200
audio_content = b"fake audio content" * 1000
files = {"audio_sample": ("test.wav", audio_content, "audio/wav")}
@@ -4078,7 +4084,7 @@ def test_voice_routes_without_tokenization(mocker: MockerFixture, method: str, h
if handler is not None:
handler._get_available_voices.return_value = []
handler.uploaded_speakers = {}
handler.delete_voice = mocker.AsyncMock(return_value=False)
handler.delete_voice = mocker.AsyncMock(side_effect=InvalidVoiceReferenceError("Voice 'missing' not found"))
app = _make_api_server_request(handler).app
app.add_api_route("/v1/audio/voices", api_server_module.list_voices, methods=["GET"])
app.add_api_route("/v1/audio/voices", api_server_module.upload_voice, methods=["POST"])
@@ -4223,7 +4229,7 @@ def test_api_server_delete_voice_value_error_returns_400(mocker: MockerFixture):
def test_api_server_delete_voice_not_found_returns_404(mocker: MockerFixture):
handler = mocker.MagicMock()
handler.delete_voice = mocker.AsyncMock(return_value=False)
handler.delete_voice = mocker.AsyncMock(side_effect=InvalidVoiceReferenceError("Voice 'missing' not found"))
raw_request = _make_api_server_request(handler, method="DELETE", path="/v1/audio/voices/missing")
response = asyncio.run(api_server_module.delete_voice("missing", raw_request))
@@ -4236,6 +4242,43 @@ def test_api_server_delete_voice_not_found_returns_404(mocker: MockerFixture):
)
def test_api_server_delete_built_in_voice_returns_403(mocker: MockerFixture):
handler = mocker.MagicMock()
handler.uploaded_speakers = set()
handler._get_available_speakers = mocker.Mock(return_value=set("built-in"))
handler.delete_voice = mocker.AsyncMock(
side_effect=InvalidPresetVoiceReferenceError("Cannot delete built-in voice 'built-in'")
)
raw_request = _make_api_server_request(handler, method="DELETE", path="/v1/audio/voices/built-in")
response = asyncio.run(api_server_module.delete_voice("built-in", raw_request))
_assert_openai_error_response(
response,
status_code=403,
message="Cannot delete built-in voice 'built-in'",
err_type="ForbiddenError",
)
def test_api_server_delete_default_voice_returns_403(mocker: MockerFixture):
handler = mocker.MagicMock()
handler.uploaded_speakers = set()
handler.delete_voice = mocker.AsyncMock(
side_effect=InvalidPresetVoiceReferenceError("Cannot delete built-in voice 'default'")
)
raw_request = _make_api_server_request(handler, method="DELETE", path="/v1/audio/voices/default")
response = asyncio.run(api_server_module.delete_voice("default", raw_request))
_assert_openai_error_response(
response,
status_code=403,
message="Cannot delete built-in voice 'default'",
err_type="ForbiddenError",
)
def test_api_server_delete_voice_exception_returns_500(mocker: MockerFixture):
handler = mocker.MagicMock()
handler.delete_voice = mocker.AsyncMock(side_effect=RuntimeError("disk failed"))