ATH-MaaS/Pixelle-Video · error · Exception

TTS generation failed: {error_msg}

Error message

TTS generation failed: {error_msg}

What it means

TTSService._call_comfyui_workflow runs a TTS ComfyUI/RunningHub workflow via kit.execute() and requires result.status == 'completed'. Any other status raises 'TTS generation failed: {error_msg}' using result.msg from ComfyKit. It reports the TTS workflow run itself failed on the backend.

Source

Thrown at pixelle_video/services/tts_service.py:261

            kit = await self.core._get_or_create_comfykit()
            
            # Determine what to pass to ComfyKit based on source
            if workflow_info["source"] == "runninghub" and "workflow_id" in workflow_info:
                # RunningHub: pass workflow_id
                workflow_input = workflow_info["workflow_id"]
                logger.info(f"Executing RunningHub TTS workflow: {workflow_input}")
            else:
                # Selfhost: pass file path
                workflow_input = workflow_info["path"]
                logger.info(f"Executing selfhost TTS workflow: {workflow_input}")
            
            result = await kit.execute(workflow_input, workflow_params)
            
            # 4. Handle result
            if result.status != "completed":
                error_msg = result.msg or "Unknown error"
                logger.error(f"TTS generation failed: {error_msg}")
                raise Exception(f"TTS generation failed: {error_msg}")
            
            # ComfyKit result can have audio files in different output types
            # Try to get audio file path from result
            audio_path = None
            
            # Check for audio files in result.audios (if available)
            if hasattr(result, 'audios') and result.audios:
                audio_path = result.audios[0]
                logger.debug(f"✅ Found audio in result.audios: {audio_path}")
            # Check for files in result.files
            elif hasattr(result, 'files') and result.files:
                audio_path = result.files[0]
                logger.debug(f"✅ Found audio in result.files: {audio_path}")
            # Check in outputs dictionary
            elif hasattr(result, 'outputs') and result.outputs:
                logger.debug(f"Searching for audio file in result.outputs: {result.outputs}")
                # Try to find audio file in outputs
                for key, value in result.outputs.items():

View on GitHub (pinned to 848b054e4f)

Solutions

  1. Read the {error_msg} suffix and logger.error output — result.msg identifies the failing backend node or reason; address that first.
  2. Validate inputs: non-empty text, a voice id the workflow actually supports, and speed within the node's accepted range.
  3. Verify the TTS workflow_id (RunningHub) or file path (selfhost) exists and is current.
  4. For selfhost, confirm the TTS custom nodes and models are installed and ComfyUI logs show no import errors; for RunningHub, check API key validity and task quota.
  5. Retry with backoff if the message indicates transient backend conditions (timeout, queue, OOM).

Example fix

// before
if result.status != "completed":
    raise Exception(f"TTS generation failed: {result.msg}")
// after
if result.status != "completed":
    logger.error(f"TTS workflow {workflow_input} failed: {result.msg}")
    raise TTSWorkflowError(workflow_input, result.status, result.msg)  # typed, actionable error
Defensive patterns

Strategy: try-catch

Validate before calling

# before calling TTS
assert text and text.strip(), "text must be non-empty"
if len(text) > MAX_TTS_CHARS:
    text = text[:MAX_TTS_CHARS]  # or chunk
if voice is not None:
    assert voice in SUPPORTED_VOICES, f"unsupported voice: {voice}"
assert 0.5 <= speed <= 2.0, "speed out of range"
# verify backend reachable / workflow_id valid before submit

Type guard

def tts_completed(result) -> bool:
    return getattr(result, "status", None) == "completed"

Try / catch

try:
    audio = await tts_service(...)
except Exception as e:
    if str(e).startswith("TTS generation failed:"):
        reason = str(e).removeprefix("TTS generation failed: ")
        logger.warning("tts workflow failed: %s", reason)
        audio = await tts_service(...)  # retry with backoff or fallback engine
    else:
        raise

Prevention

When it happens

Trigger: Calling TTSService.__call__ where kit.execute(workflow_input, workflow_params) returns a non-'completed' status — backend node error in the TTS graph, invalid/missing 'text' or 'voice' parameter, unknown workflow_id, RunningHub task failure/timeout, or ComfyUI missing the TTS custom nodes.

Common situations: Voice id not supported by the deployed TTS node; text too long for the node's limits; selfhost ComfyUI missing the TTS custom node pack or model weights; stale RunningHub workflow_id after republishing; API key or quota problems on RunningHub.

Related errors


AI-assisted analysis of ATH-MaaS/Pixelle-Video@848b054e4f (2026-08-30). Data as JSON: /api/errors/b82f6538e3440422. Report an issue: GitHub.