instructure/canvas-lms · error
unable to handle state change: #
Error message
unable to handle state change: #{asked_state} What it means
UpdateAssignment mutation's resolve handles 'unpublished', 'published', and 'deleted' asked states; anything else hits this raise. It is the exhaustive-case guard converting workflow state into published flags and side effects.
Solutions
- Send only 'published', 'unpublished', or 'deleted' as state
- Share an enum constant between client and mutation input to prevent drift
- Improve the raise to a GraphQL::ExecutionError naming the valid options
Example fix
# before
raise "unable to handle state change: #{asked_state}"
# after
raise GraphQL::ExecutionError, "unable to handle state change: #{asked_state} (expected published, unpublished, or deleted)" Defensive patterns
Strategy: validation
Validate before calling
const allowedStates = ['published', 'unpublished', 'deleted'];
if (state && !allowedStates.includes(state)) {
throw new Error(`state must be one of ${allowedStates.join(', ')}`);
} Type guard
function isUpdateState(s) {
return ['published', 'unpublished', 'deleted'].includes(s);
} Try / catch
try {
await updateAssignment({ state });
} catch (e) {
if (/unable to handle state change/.test(e.message)) {
showError('Supported states: published, unpublished, deleted.');
}
} Prevention
- Use a shared enum for assignment workflow states
- Add unit tests covering every enum member in the case statement
- Keep client state machine and mutation enum in sync after upgrades
When it happens
Trigger: Calling updateAssignment with a state value outside {unpublished, published, deleted}, e.g. 'archived', 'draft', or a casing typo ('Published').
Common situations: Older client code sending states removed from the supported set; typos in GraphQL variables; frontend state machine drift.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- unable to handle state change: #
- All ConversationMessages must exist within the same…
- An unexpected error occurred while grading.
- An unexpected error occurred while submitting feedback.
- Assignment group category id and discussion topic group…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/55c6eb3c38e9d49c.
Report an issue: GitHub.
Appendix: source
Thrown at app/graphql/mutations/update_assignment.rb:61
# input. first, update_api_assignment doesnt expect a :state key. instead,
# it expects a :published key of boolean type.
# also, if we are required to transition to restored or destroyed, then we
# need to handle those as well.
input_hash = input.to_h
other_update_on_assignment = false
if input_hash.key? :state
asked_state = input_hash.delete :state
case asked_state
when "unpublished"
input_hash[:published] = false
other_update_on_assignment = :ensure_restored
when "published"
input_hash[:published] = true
other_update_on_assignment = :ensure_restored
when "deleted"
other_update_on_assignment = :ensure_destroyed
else
raise "unable to handle state change: #{asked_state}"
end
end
# modifies input_hash
prepare_input_params!(input_hash, update_proxy)
module_ids = prepare_module_ids!(input_hash)
# make sure to do other required updates
send(other_update_on_assignment) if other_update_on_assignment
# ensure the assignment is part of all required modules
ensure_modules(module_ids) if module_ids
# normal update now
@working_assignment.content_being_saved_by(current_user)
@working_assignment.updating_user = current_user
result = update_proxy.update_api_assignment(@working_assignment, ActionController::Parameters.new(input_hash), current_user, @working_assignment.context)View on GitHub (pinned to 1c9f0bb801)