instructure/canvas-lms · error

final grade publishing disabled

Error message

final grade publishing disabled

What it means

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.

Solutions

  1. Enable the grade_export plugin in the account/plugin settings (or config/ plugins YAML)
  2. Verify with Canvas::Plugin.find!('grade_export').enabled? before calling publish_final_grades
  3. If publishing is not intended, use the regular grade posting flow instead of SIS publishing

Example fix

// before
course.publish_final_grades(teacher)
// after
plugin = Canvas::Plugin.find!('grade_export')
raise 'enable grade_export plugin' unless plugin.enabled?
course.publish_final_grades(teacher)
Defensive patterns

Strategy: validation

Validate before calling

unless Canvas::Plugin.find!('grade_export').enabled?
  raise 'enable grade_export plugin before publishing final grades'
end
course.publish_final_grades(user)

Type guard

null

Try / catch

begin
  course.publish_final_grades(user)
rescue RuntimeError => e
  raise unless e.message == 'final grade publishing disabled'
  # notify admin to enable the grade_export plugin
end

Prevention

When it happens

Trigger: Calling course.publish_final_grades when Canvas::Plugin.find!('grade_export') returns a plugin whose enabled? is false (or the plugin is not installed).

Common situations: 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.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/e82afdaa1f2f9244. Report an issue: GitHub.

Appendix: source

Thrown at app/models/course.rb:2606

    }
  end

  def allows_grade_publishing_by(user)
    return false unless Canvas::Plugin.find!("grade_export").enabled?

    settings = Canvas::Plugin.find!("grade_export").settings
    format_settings = Course.valid_grade_export_types[settings[:format_type]]
    return false unless format_settings
    return false if SisPseudonym.for(user, self).nil? && format_settings[:requires_publishing_pseudonym]

    true
  end

  def publish_final_grades(publishing_user, user_ids_to_publish = nil)
    # we want to set all the publishing statuses to 'pending' immediately,
    # and then as a delayed job, actually go publish them.

    raise "final grade publishing disabled" unless Canvas::Plugin.find!("grade_export").enabled?

    settings = Canvas::Plugin.find!("grade_export").settings

    last_publish_attempt_at = Time.now.utc
    scope = student_enrollments.not_fake
    scope = scope.where(user_id: user_ids_to_publish) if user_ids_to_publish
    scope.update_all(grade_publishing_status: "pending",
                     grade_publishing_message: nil,
                     last_publish_attempt_at:)

    delay_if_production(n_strand: ["send_final_grades_to_endpoint", global_root_account_id])
      .send_final_grades_to_endpoint(publishing_user, user_ids_to_publish)
    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?
  end

  def send_final_grades_to_endpoint(publishing_user, user_ids_to_publish = nil)
    # actual grade publishing logic is here, but you probably want
    # 'publish_final_grades'

View on GitHub (pinned to 1c9f0bb801)