instructure/canvas-lms · error · NoTransitionAllowed
There is no event # defined for the # state
Error message
There is no event #{name.to_sym} defined for the #{current_state} state What it means
The workflow gem's process_event! raises NoTransitionAllowed when the requested event name is not defined on the object's current state. State machines have per-state event maps; calling an event that exists on other states but not this one is invalid.
Solutions
- Check the valid events for the current state before calling (current_state.events.key?(name)) or use the non-bang process_event which returns false instead of raising
- Reload the record to get the freshest state before transitioning
- Guard the UI to only render valid events for the record's state
- Rescue NoTransitionAllowed and handle the stale-transition case gracefully
Example fix
// before
record.process_event!(:publish)
// after
if record.current_state.events.key?(:publish)
record.process_event!(:publish)
else
Rails.logger.warn("publish not valid in #{record.current_state}")
end Defensive patterns
Strategy: try-catch
Validate before calling
if obj.current_state.events.key?(event_name) obj.process_event!(event_name) end
Try / catch
begin
obj.process_event!(event_name)
rescue Workflow::NoTransitionAllowed
Rails.logger.warn("#{event_name} invalid in #{obj.current_state}")
obj.reload
end Prevention
- Reload records before transitions in concurrent flows
- Only render UI actions valid for the current state
- Prefer the non-bang process_event when raising is undesired
- Document per-state event maps for custom workflows
When it happens
Trigger: Calling obj.process_event!(:approve) when the current_state has no :approve event (e.g. approving an already-approved record); invoking events on records in terminal states; calling events in the wrong lifecycle order.
Common situations: Race conditions where two requests transition the same record and the second sees an updated state; stale UI data showing buttons for events no longer valid; missing state in a newly added workflow step.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- can't accept
- `increment_completion!` can only be invoked after a total…
- A new_id, '# ', referenced an existing # and the # with #…
- A new_integration_id, '#
- A student referenced a non-existent user #
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/401079a29f2d91ac.
Report an issue: GitHub.
Appendix: source
Thrown at gems/workflow/lib/workflow.rb:193
@halted_because
end
# INSTRUCTURE:
def process_event(name, *)
success = true
begin
process_event!(name, *)
rescue NoTransitionAllowed
@halted = true
@halted_because = $!
success = false
end
success
end
def process_event!(name, *)
event = current_state.events[name.to_sym]
raise NoTransitionAllowed, "There is no event #{name.to_sym} defined for the #{current_state} state" if event.nil?
@halted_because = nil
@halted = false
@raise_exception_on_halt = false
return_value = run_action(event.action, *) || run_action_callback("do_#{event.name}", *)
if @halted
if @raise_exception_on_halt
raise TransitionHalted, @halted_because
else
false
end
else
run_on_transition(current_state, spec.states[event.transitions_to], name, *)
transition(current_state, spec.states[event.transitions_to], name, *)
return_value
end
end
View on GitHub (pinned to 1c9f0bb801)