{"record":{"id":"7310151ab663ea5e","repo":"instructure/canvas-lms","slug":"custom-grade-status-not-found","errorCode":null,"errorMessage":"custom grade status not found","messagePattern":"custom grade status not found","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/mutations/delete_custom_grade_status.rb","lineNumber":44,"sourceCode":"      raise GraphQL::ExecutionError, \"custom gradebook statuses feature flag is disabled\" unless Account.site_admin.feature_enabled?(:custom_gradebook_statuses)\n\n      custom_grade_status = CustomGradeStatus.active.find(input[:id])\n\n      unless custom_grade_status.grants_right?(current_user, session, :delete)\n        raise GraphQL::ExecutionError, I18n.t(\"Insufficient permissions\")\n      end\n\n      context[:deleted_models] ||= {}\n      context[:deleted_models][:custom_grade_status] = custom_grade_status\n      custom_grade_status_id = custom_grade_status.id\n      custom_grade_status.deleted_by = current_user\n      custom_grade_status.destroy\n\n      InstStatsd::Statsd.distributed_increment(\"custom_grade_status.graphql.delete\")\n\n      { custom_grade_status_id: }\n    rescue ActiveRecord::RecordNotFound\n      raise GraphQL::ExecutionError, \"custom grade status not found\"\n    end\n\n    def self.custom_grade_status_id_log_entry(_entry, context)\n      context[:deleted_models][:custom_grade_status]\n    end\n  end\nend\n","sourceCodeStart":26,"sourceCodeEnd":52,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/delete_custom_grade_status.rb#L26-L52","documentation":"GraphQL::ExecutionError raised in the rescue ActiveRecord::RecordNotFound branch of Mutations::DeleteCustomGradeStatus#resolve when CustomGradeStatus.active.find(input[:id]) finds no active record with that id (deleted, wrong id, or never existed).","triggerScenarios":"Passing an id of a status that was already destroyed, is soft-deleted (excluded by .active), or does not exist.","commonSituations":"Double-clicking delete so the second call hits an already-deleted record; stale lists in the gradebook UI after another teacher deleted a status; test fixtures cleaned between runs.","solutions":["Check CustomGradeStatus.active.exists?(id) before calling the mutation","Handle the error gracefully in the client by refreshing the status list","Use find_by and skip deletion if already gone for idempotent flows","Verify the id format (relay vs legacy) matches the argument prepare function"],"exampleFix":"// before\n// second click after delete\nawait deleteCustomGradeStatus({ id }) // 'custom grade status not found'\n// after\nif (statusList.some(s => s.id === id)) {\n  await deleteCustomGradeStatus({ id })\n}","handlingStrategy":"validation","validationCode":"if (!activeStatuses.some(s => s.id === id)) return // nothing to delete","typeGuard":null,"tryCatchPattern":"try {\n  await deleteCustomGradeStatus(id)\n} catch (e) {\n  if (/not found/.test(e.message)) removeFromLocalList(id) // already gone\n}","preventionTips":["Disable the delete button after the first click","Refresh status lists after other users' changes","Treat not-found as idempotent success"],"tags":["graphql","not-found","gradebook"],"backgroundTag":"record-not-found","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"}