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
- 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
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
- 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
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
- endpoint undefined
- grade publishing requires a grading standard
- unknown format type: #
- assessor and assessee required
- association required
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)