{"record":{"id":"e82afdaa1f2f9244","repo":"instructure/canvas-lms","slug":"final-grade-publishing-disabled","errorCode":null,"errorMessage":"final grade publishing disabled","messagePattern":"final grade publishing disabled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/models/course.rb","lineNumber":2606,"sourceCode":"    }\n  end\n\n  def allows_grade_publishing_by(user)\n    return false unless Canvas::Plugin.find!(\"grade_export\").enabled?\n\n    settings = Canvas::Plugin.find!(\"grade_export\").settings\n    format_settings = Course.valid_grade_export_types[settings[:format_type]]\n    return false unless format_settings\n    return false if SisPseudonym.for(user, self).nil? && format_settings[:requires_publishing_pseudonym]\n\n    true\n  end\n\n  def publish_final_grades(publishing_user, user_ids_to_publish = nil)\n    # we want to set all the publishing statuses to 'pending' immediately,\n    # and then as a delayed job, actually go publish them.\n\n    raise \"final grade publishing disabled\" unless Canvas::Plugin.find!(\"grade_export\").enabled?\n\n    settings = Canvas::Plugin.find!(\"grade_export\").settings\n\n    last_publish_attempt_at = Time.now.utc\n    scope = student_enrollments.not_fake\n    scope = scope.where(user_id: user_ids_to_publish) if user_ids_to_publish\n    scope.update_all(grade_publishing_status: \"pending\",\n                     grade_publishing_message: nil,\n                     last_publish_attempt_at:)\n\n    delay_if_production(n_strand: [\"send_final_grades_to_endpoint\", global_root_account_id])\n      .send_final_grades_to_endpoint(publishing_user, user_ids_to_publish)\n    delay(run_at: last_publish_attempt_at + settings[:success_timeout].to_i.seconds).expire_pending_grade_publishing_statuses(last_publish_attempt_at) if should_kick_off_grade_publishing_timeout?\n  end\n\n  def send_final_grades_to_endpoint(publishing_user, user_ids_to_publish = nil)\n    # actual grade publishing logic is here, but you probably want\n    # 'publish_final_grades'","sourceCodeStart":2588,"sourceCodeEnd":2624,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/course.rb#L2588-L2624","documentation":"Guard in Course#publish_final_grades: the grade_export plugin is disabled (or misconfigured), so final grade publishing is refused with this sentinel error. It fires inside the publishing job before any per-student posting begins.","triggerScenarios":"Calling course.publish_final_grades when Canvas::Plugin.find!('grade_export') returns a plugin whose enabled? is false (or the plugin is not installed).","commonSituations":"Self-hosted or dev environments without the grade_export/SIS integration plugin configured; attempting SIS grade publishing in test setups; plugin disabled in account plugin settings.","solutions":["Enable the grade_export plugin in the account/plugin settings (or config/ plugins YAML)","Verify with Canvas::Plugin.find!('grade_export').enabled? before calling publish_final_grades","If publishing is not intended, use the regular grade posting flow instead of SIS publishing"],"exampleFix":"// before\ncourse.publish_final_grades(teacher)\n// after\nplugin = Canvas::Plugin.find!('grade_export')\nraise 'enable grade_export plugin' unless plugin.enabled?\ncourse.publish_final_grades(teacher)","handlingStrategy":"validation","validationCode":"unless Canvas::Plugin.find!('grade_export').enabled?\n  raise 'enable grade_export plugin before publishing final grades'\nend\ncourse.publish_final_grades(user)","typeGuard":"null","tryCatchPattern":"begin\n  course.publish_final_grades(user)\nrescue RuntimeError => e\n  raise unless e.message == 'final grade publishing disabled'\n  # notify admin to enable the grade_export plugin\nend","preventionTips":["Verify plugin enabled? before offering grade publishing in the UI","Keep plugin settings consistent across environments","Use standard grade posting when SIS publishing is not configured"],"tags":["ruby","rails","grades","plugin"],"backgroundTag":"feature-not-enabled","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"}