Add support for exception handling as part of transitions
You have an idea for a feature that would make transitions more helpful or easier to use? Great! We are looking forward to your suggestion.
Is your feature request related to a problem? Please describe. Currently, when an exception occurs during a transition (in before, after, on_enter, or on_exit callbacks), the flow is interrupted and the exception must be handled externally via try/except in the application code. This forces developers to step outside of the FSM logic, breaking cohesion and increasing maintenance complexity.
Describe the solution you'd like It would be helpful to allow transitions to specify an alternative target state in case of an exception. If an error occurs during the execution of a transition, the machine should automatically redirect to a user-defined “error” state. This would make exceptions part of the FSM graph itself, keeping error handling consistent within the state machine model and avoiding the need to capture exceptions outside of it.
Additional context This feature would be especially valuable in scenarios where workflows must explicitly define failure paths, such as business processes, orchestration systems, or critical applications where each transition may have both a success route and a failure route. This would make FSM modeling more expressive and aligned with real-world expectations.
Hello @jrobertogram,
It would be helpful to allow transitions to specify an alternative target state in case of an exception. If an error occurs during the execution of a transition, the machine should automatically redirect to a user-defined “error” state.
Transitions features an on_exception callback as state in the Readme's callback section:
from transitions import Machine
class Matter(object):
def raise_error(self, event): raise ValueError("Oh no")
def handle_error(self, event):
print("Fixing things ...")
del event.error # it did not happen if we cannot see it ...
states=['solid', 'liquid', 'gas', 'plasma']
lump = Matter()
m = Machine(lump, states, before_state_change='raise_error', on_exception='handle_error', send_event=True)
try:
lump.to_gas()
except ValueError:
pass
print(lump.state)
Instead of explicitly handling your error, you could also pass an event that cause the transition to your error state:
transitions = [ # ...
["error", "*", "error_state"],
]
# ...
m = Machine(model, states=states, transitions=transitions, on_exception='error', send_event=True)
Transitions will attach a caught error to the processed Event. That's wht send_event is necessary as of now to handle it. Also note that if the transition to your error_state also throws errors, you may be caught in an infinite loop.
Please let me know if this is what you are looking for or whether you had something different in mind.