{"record":{"id":"55c6eb3c38e9d49c","repo":"instructure/canvas-lms","slug":"unable-to-handle-state-change-asked-state-update-assignment","errorCode":null,"errorMessage":"unable to handle state change: #{asked_state}","messagePattern":"unable to handle state change: #(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/update_assignment.rb","lineNumber":61,"sourceCode":"    # input. first, update_api_assignment doesnt expect a :state key. instead,\n    # it expects a :published key of boolean type.\n    # also, if we are required to transition to restored or destroyed, then we\n    # need to handle those as well.\n    input_hash = input.to_h\n    other_update_on_assignment = false\n    if input_hash.key? :state\n      asked_state = input_hash.delete :state\n      case asked_state\n      when \"unpublished\"\n        input_hash[:published] = false\n        other_update_on_assignment = :ensure_restored\n      when \"published\"\n        input_hash[:published] = true\n        other_update_on_assignment = :ensure_restored\n      when \"deleted\"\n        other_update_on_assignment = :ensure_destroyed\n      else\n        raise \"unable to handle state change: #{asked_state}\"\n      end\n    end\n\n    # modifies input_hash\n    prepare_input_params!(input_hash, update_proxy)\n\n    module_ids = prepare_module_ids!(input_hash)\n\n    # make sure to do other required updates\n    send(other_update_on_assignment) if other_update_on_assignment\n\n    # ensure the assignment is part of all required modules\n    ensure_modules(module_ids) if module_ids\n\n    # normal update now\n    @working_assignment.content_being_saved_by(current_user)\n    @working_assignment.updating_user = current_user\n    result = update_proxy.update_api_assignment(@working_assignment, ActionController::Parameters.new(input_hash), current_user, @working_assignment.context)","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/update_assignment.rb#L43-L79","documentation":"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.","triggerScenarios":"Calling updateAssignment with a state value outside {unpublished, published, deleted}, e.g. 'archived', 'draft', or a casing typo ('Published').","commonSituations":"Older client code sending states removed from the supported set; typos in GraphQL variables; frontend state machine drift.","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"],"exampleFix":"# before\nraise \"unable to handle state change: #{asked_state}\"\n# after\nraise GraphQL::ExecutionError, \"unable to handle state change: #{asked_state} (expected published, unpublished, or deleted)\"","handlingStrategy":"validation","validationCode":"const allowedStates = ['published', 'unpublished', 'deleted'];\nif (state && !allowedStates.includes(state)) {\n  throw new Error(`state must be one of ${allowedStates.join(', ')}`);\n}","typeGuard":"function isUpdateState(s) {\n  return ['published', 'unpublished', 'deleted'].includes(s);\n}","tryCatchPattern":"try {\n  await updateAssignment({ state });\n} catch (e) {\n  if (/unable to handle state change/.test(e.message)) {\n    showError('Supported states: published, unpublished, deleted.');\n  }\n}","preventionTips":["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"],"tags":["graphql","mutation","assignments","state"],"backgroundTag":"invalid-enum-value","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}