Skip to content

symfonic.agent.cutover.errors

errors

The one exception the migrated run raises that legacy also raised.

An exhausted round budget is the only failure whose type an adopter's code already keys on: the legacy body lets LangGraph's GraphRecursionError propagate out of SymfonicAgent.run, so except GraphRecursionError is documented, working adopter code today. A cutover that swapped it for a SymfonicAgentError would keep "parity of kind" — both still fail loudly — while breaking the observable the except clause actually reads, and the turn would sail past the handler into the caller's top-level catch.

So the migrated path raises a type that is both. The ancestry is a widening, never a rename: except GraphRecursionError catches exactly what it caught before the flip, except SymfonicAgentError (and except SymfonicError) catch it too, and the message says which budget ran out.

RecursionExhaustedError

RecursionExhaustedError(message: str, code: str | None = None)

Bases: GraphRecursionError, SymfonicAgentError

The invocation used every model round its budget allows.

Inherits from both hierarchies on purpose — see the module docstring. The LangGraph base comes first so GraphRecursionError's own args handling wins, and SymfonicAgentError.__init__ still supplies the optional code.

Source code in src/symfonic/agent/cutover/errors.py
def __init__(self, message: str, code: str | None = None) -> None:
    SymfonicAgentError.__init__(self, message, code)