{"record":{"id":"85e9ccb224c018c6","repo":"harry0703/MoneyPrinterTurbo","slug":"unsupported-minimax-voice-type-voice-type","errorCode":null,"errorMessage":"Unsupported MiniMax voice type: {voice_type}","messagePattern":"Unsupported MiniMax voice type: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"app/services/voice.py","lineNumber":1385,"sourceCode":"        if inferred_url:\n            return inferred_url\n    return _resolve_minimax_tts_url(config.minimax_tts.get(\"base_url\", \"\"))\n\n\ndef get_minimax_voice_catalog(\n    api_key: str = \"\",\n    endpoint: str = \"\",\n    voice_type: str = \"all\",\n) -> list[dict[str, str]]:\n    \"\"\"\n    查询当前 MiniMax 账号可用的系统、克隆和生成音色。\n\n    返回值统一为 voice_id、voice_name、voice_type 三个字段，调用方无需了解\n    MiniMax 按音色来源拆分数组的响应结构。查询失败时抛出异常，让 WebUI、\n    API 或 CLI 可以按各自交互方式展示明确错误，而不是静默返回空列表。\n    \"\"\"\n    if voice_type not in {\"system\", \"voice_cloning\", \"voice_generation\", \"all\"}:\n        raise ValueError(f\"Unsupported MiniMax voice type: {voice_type}\")\n\n    effective_api_key = str(api_key or get_minimax_tts_api_key()).strip()\n    if not effective_api_key:\n        raise ValueError(\"MiniMax TTS API key is not set\")\n\n    tts_endpoint = (\n        _resolve_minimax_tts_url(endpoint)\n        if endpoint\n        else get_minimax_tts_endpoint()\n    )\n    voice_endpoint = (\n        f\"{tts_endpoint[:-len('/t2a_v2')]}/get_voice\"\n        if tts_endpoint.endswith(\"/t2a_v2\")\n        else f\"{tts_endpoint.rstrip('/')}/get_voice\"\n    )\n    response = requests.post(\n        voice_endpoint,\n        json={\"voice_type\": voice_type},","sourceCodeStart":1367,"sourceCodeEnd":1403,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/app/services/voice.py#L1367-L1403","documentation":"Input validation in the MiniMax voice-catalog query: voice_type must be one of 'system', 'voice_cloning', 'voice_generation', or 'all'. Any other string raises ValueError immediately, before any API key or network work is done.","triggerScenarios":"Calling the MiniMax get-voice listing function with a typo'd or unsupported voice_type such as 'System', 'cloned', 'voice-clone', or 'default'.","commonSituations":"Caller passes an unvalidated user-supplied filter straight from a WebUI dropdown or CLI flag; casing mismatch ('System' vs 'system'); value copied from MiniMax docs that uses a different naming scheme.","solutions":["Use one of the exact allowed values: 'system', 'voice_cloning', 'voice_generation', 'all' (lowercase).","Validate/lowercase the input before calling, surfacing the allowed set to the user in the UI."],"exampleFix":"# before\nvoices = list_minimax_voices(voice_type=\"cloned\")\n\n# after\n_ALLOWED = {\"system\", \"voice_cloning\", \"voice_generation\", \"all\"}\nvoice_type = voice_type if voice_type in _ALLOWED else \"all\"\nvoices = list_minimax_voices(voice_type=voice_type)","handlingStrategy":"validation","validationCode":"ALLOWED_MINIMAX_VOICE_TYPES = {\"system\", \"voice_cloning\", \"voice_generation\", \"all\"}\n\nif voice_type not in ALLOWED_MINIMAX_VOICE_TYPES:\n    voice_type = \"all\"  # or raise with the allowed set in the message","typeGuard":"def is_valid_minimax_voice_type(value: str) -> bool:\n    return isinstance(value, str) and value in {\n        \"system\", \"voice_cloning\", \"voice_generation\", \"all\"\n    }","tryCatchPattern":null,"preventionTips":["Derive UI dropdown options from the allowed set so users cannot submit invalid values.","Lowercase and trim user input before passing it through."],"tags":["minimax","tts","validation"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}