home-assistant/core · error · InvalidPipelineStagesError
validation-error
validation-error
Error message
Invalid stage combination: start={start_stage}, end={end_stage} What it means
InvalidPipelineStagesError raised in PipelineRun.__post_init__ when the requested run stages are misordered: in the wake -> stt -> intent -> tts pipeline, the end stage appears before the start stage in PIPELINE_STAGE_ORDER, so the run would be empty/negative. Its message ('Invalid stage combination: start={start_stage}, end={end_stage}') carries the offending pair.
Source
Thrown at homeassistant/components/assist_pipeline/pipeline.py:608
_intent_agent_only = False
"""If request should only be handled by agent.
Ignores sentence triggers and local processing.
"""
_streamed_response_text = False
"""If the conversation agent streamed response text to TTS result."""
def __post_init__(self) -> None:
"""Set language for pipeline."""
self.language = self.pipeline.language or self.hass.config.language
# wake -> stt -> intent -> tts
if PIPELINE_STAGE_ORDER.index(self.end_stage) < PIPELINE_STAGE_ORDER.index(
self.start_stage
):
raise InvalidPipelineStagesError(self.start_stage, self.end_stage)
pipeline_data = self.hass.data[KEY_ASSIST_PIPELINE]
if self.pipeline.id not in pipeline_data.pipeline_debug:
pipeline_data.pipeline_debug[self.pipeline.id] = LimitedSizeDict(
size_limit=STORED_PIPELINE_RUNS
)
pipeline_data.pipeline_debug[self.pipeline.id][self.id] = PipelineRunDebug()
pipeline_data.pipeline_runs.add_run(self)
# Initialize with audio settings
if self.audio_settings.needs_processor and (self.audio_enhancer is None):
# Default audio enhancer
self.audio_enhancer = MicroVadSpeexEnhancer(
self.audio_settings.auto_gain_dbfs,
self.audio_settings.noise_suppression_level,
self.audio_settings.is_vad_enabled,
)
View on GitHub (pinned to 58a3fdb3ea)
Solutions
- Order stages along wake -> stt -> intent -> tts (start must not come after end).
- Validate stage names and order against PIPELINE_STAGE_ORDER before constructing PipelineRun.
- If you only need a suffix/slice of the pipeline, pick start/end from the ordered constant list programmatically.
Example fix
# before run = PipelineRun(hass, pipeline, start_stage="intent", end_stage="stt") # after run = PipelineRun(hass, pipeline, start_stage="stt", end_stage="tts")
Defensive patterns
Strategy: validation
Validate before calling
from homeassistant.components.assist_pipeline.pipeline import PIPELINE_STAGE_ORDER
def stages_valid(start: str, end: str) -> bool:
return PIPELINE_STAGE_ORDER.index(end) >= PIPELINE_STAGE_ORDER.index(start) Try / catch
Validate stage order (or catch InvalidPipelineStagesError) when accepting user-specified run stages, and normalize/reject before constructing PipelineRun.
Prevention
- Derive start/end stages from PIPELINE_STAGE_ORDER instead of free-text.
- Use fixed stage pairs (wake..tts, stt..tts) in callers.
- Test stage configs after upgrading HA, as stage constants can evolve.
When it happens
Trigger: Constructing PipelineRun with e.g. start_stage='intent' and end_stage='stt', or passing stage names from websocket options that were not validated (including case mismatches yielding wrong indices indirectly).
Common situations: Programmatic pipeline runs with hand-built stage arguments; frontends exposing free-text stage pickers; code updated after stage constants were renamed/reordered.
Related errors
- pipeline_not_found
- noise_suppression_level must be in [0, 4]
- auto_gain_dbfs must be in [0, 31]
- username_not_normalized
- Operation mode not supported
AI-assisted analysis of home-assistant/core@58a3fdb3ea (2026-08-14).
Data as JSON: /api/errors/9af75103001fa5ff.
Report an issue: GitHub.