microsoft/autogen · error · RuntimeError

Termination condition has already been reached

Error message

Termination condition has already been reached

What it means

OrTerminationCondition raises RuntimeError (note: not TerminatedException like the other conditions — a known inconsistency) if called after any of its sub-conditions has already terminated. The terminated property is any(condition.terminated), so a single fired sub-condition locks the whole Or condition.

Source

Thrown at python/packages/autogen-agentchat/src/autogen_agentchat/base/_termination.py:158

    conditions: List[ComponentModel]
    """List of termination conditions where any one being satisfied is sufficient."""


class OrTerminationCondition(TerminationCondition, Component[OrTerminationConditionConfig]):
    component_config_schema = OrTerminationConditionConfig
    component_type = "termination"
    component_provider_override = "autogen_agentchat.base.OrTerminationCondition"

    def __init__(self, *conditions: TerminationCondition) -> None:
        self._conditions = conditions

    @property
    def terminated(self) -> bool:
        return any(condition.terminated for condition in self._conditions)

    async def __call__(self, messages: Sequence[BaseAgentEvent | BaseChatMessage]) -> StopMessage | None:
        if self.terminated:
            raise RuntimeError("Termination condition has already been reached")
        stop_messages = await asyncio.gather(*[condition(messages) for condition in self._conditions])
        stop_messages_filter = [stop_message for stop_message in stop_messages if stop_message is not None]
        if len(stop_messages_filter) > 0:
            content = ", ".join(stop_message.content for stop_message in stop_messages_filter)
            source = ", ".join(stop_message.source for stop_message in stop_messages_filter)
            return StopMessage(content=content, source=source)
        return None

    async def reset(self) -> None:
        for condition in self._conditions:
            await condition.reset()

    def _to_config(self) -> OrTerminationConditionConfig:
        """Convert the OR termination condition to a config."""
        return OrTerminationConditionConfig(conditions=[condition.dump_component() for condition in self._conditions])

    @classmethod
    def _from_config(cls, config: OrTerminationConditionConfig) -> Self:

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Check or_condition.terminated before calling it
  2. await or_condition.reset() (or team.reset()) between runs
  3. When catching, handle both exception types: except (TerminatedException, RuntimeError) — this site raises bare RuntimeError

Example fix

# before
stop = await or_condition(messages)  # raises RuntimeError after termination

# after
stop = None if or_condition.terminated else await or_condition(messages)
Defensive patterns

Strategy: validation

Validate before calling

if or_cond.terminated:
    await or_cond.reset()
stop = await or_cond(messages)

Try / catch

# NOTE: this site raises bare RuntimeError, not TerminatedException
try:
    stop = await or_cond(messages)
except (RuntimeError, TerminatedException) as e:  # from autogen_agentchat.conditions import TerminatedException
    if "already been reached" in str(e):
        await or_cond.reset()
        stop = await or_cond(messages)
    else:
        raise

Prevention

When it happens

Trigger: Invoking await or_condition(messages) after one sub-condition already returned a StopMessage; sharing sub-conditions between an OrTerminationCondition and a team's own condition; calling a run loop a second time without resetting the Or condition.

Common situations: Composing OrTerminationCondition(MaxMessageTermination(5), TimeoutTermination(60)) and reusing it across team runs; catching only TerminatedException and missing this RuntimeError variant.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/005bcd767445ca09. Report an issue: GitHub.