calesthio/OpenMontage · error · ValueError
voice_id is required for Kling official TTS
Error message
voice_id is required for Kling official TTS
What it means
Raised by kling_tts._build_request when voice_id is missing or whitespace-only. Unlike some TTS providers, Kling official TTS has no default voice — the voice must be chosen explicitly, so the wrapper rejects the request before any API call.
Source
Thrown at tools/audio/kling_tts.py:203
**self._account_usage_result(inputs, client),
**self._callback_result_data(inputs, task_id),
},
artifacts=[str(path) for path in paths],
cost_usd=self.estimate_cost(inputs),
duration_seconds=round(time.time() - start, 2),
model="kling-official-tts",
)
def _build_request(self, inputs: dict[str, Any]) -> dict[str, Any]:
text = str(inputs.get("text") or "").strip()
if not text:
raise ValueError("text is required")
if len(text) > 5000:
raise ValueError("text exceeds Kling TTS safety limit of 5000 characters")
voice_id = str(inputs.get("voice_id") or "").strip()
if not voice_id:
raise ValueError("voice_id is required for Kling official TTS")
voice_language = str(inputs.get("voice_language") or "en")
if voice_language not in TTS_LANGUAGES:
raise ValueError(f"voice_language must be one of: {', '.join(TTS_LANGUAGES)}")
voice_speed = float(inputs.get("voice_speed", 1.0))
if voice_speed < TTS_SPEED_MIN or voice_speed > TTS_SPEED_MAX:
raise ValueError(f"voice_speed must be between {TTS_SPEED_MIN} and {TTS_SPEED_MAX}")
payload: dict[str, Any] = {
"text": text,
"voice_id": voice_id,
"voice_language": voice_language,
"voice_speed": voice_speed,
}
self._copy_common_task_fields(inputs, payload)
return {
"protocol": "classic",View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Pass a valid Kling voice_id in inputs
- Fetch the official voice list first and have the user/pipeline pick one
- Validate inputs against the tool's required schema before dispatch
Example fix
// before
inputs = {"text": "hi"} # no voice_id
// after
inputs = {"text": "hi", "voice_id": "your-voice-id"} Defensive patterns
Strategy: validation
Validate before calling
if not str(inputs.get("voice_id") or "").strip():
raise ValueError("voice_id is required; fetch the Kling voice list first") Type guard
def has_voice_id(inputs: dict) -> bool:
return bool(str(inputs.get("voice_id") or "").strip()) Prevention
- Kling has no default voice — always resolve one explicitly
- Cache the fetched voice list and reference entries by id
- Check the exact key name voice_id in config files
When it happens
Trigger: Calling the tool without voice_id, or with voice_id: '' after stripping; configs copied from a different TTS tool that defaulted the voice.
Common situations: Migrating from a provider where voice was optional; voice list fetched dynamically and the fetch returned nothing; config key typo (voice vs voice_id).
Related errors
- text is required
- text exceeds Kling TTS safety limit of 5000 characters
- voice_language must be one of: {', '.join(TTS_LANGUAGES)}
- voice_speed must be between {TTS_SPEED_MIN} and {TTS_SPEED_M
- element_list must be a list of element ids or objects
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/1d3429e1a6f67795.
Report an issue: GitHub.