instructure/canvas-lms · error · Canvas::Migration::Error
User isn't allowed to edit global outcomes
Error message
User isn't allowed to edit global outcomes
What it means
Canvas::Migration::Error raised in Converter#export when Account.site_admin.grants_right?(content_migration.user, :manage_global_outcomes) is false. Same permission rule as the top-level academic_benchmark.rb check, enforced inside the converter itself.
Solutions
- Run the import with a user holding manage_global_outcomes on Account.site_admin.
- Grant the permission via a site-admin role or role override for the service account.
- Pre-check with Account.site_admin.grants_right?(cm.user, :manage_global_outcomes) before creating the migration.
- Verify cm.user is set and not nil (nil user implies no rights).
Example fix
// before cm = ContentMigration.create!(context: Account.site_admin, user: teacher) converter.export // after admin = User.site_admin_user # must hold manage_global_outcomes cm = ContentMigration.create!(context: Account.site_admin, user: admin) converter.export
Defensive patterns
Strategy: validation
Validate before calling
precheck = Account.site_admin.grants_right?(cm.user, :manage_global_outcomes) raise PermissionError, 'user lacks manage_global_outcomes' unless precheck
Try / catch
begin converter.export rescue Canvas::Migration::Error => e cm.update_attribute(:last_error, e.message) raise end
Prevention
- Verify the service account's permissions after any role changes.
- Run imports only with site-admin users.
- Check grants_right? before creating the ContentMigration.
When it happens
Trigger: Calling export on a converter whose content_migration.user lacks the manage_global_outcomes right on the site admin account.
Common situations: Import jobs executed after a user's permissions were downgraded; automation using service accounts without site-admin outcomes permission; multi-shard setups where grants_right? resolves on the wrong account.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Not importing academic benchmark data because user with ID…
- Do not look up MediaObjects by media_id - use the scope…
- File access denied
- Insufficient permissions
- Insufficient permissions to create group set
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/4055c32a16e158e4.
Report an issue: GitHub.
Appendix: source
Thrown at gems/plugins/academic_benchmark/lib/academic_benchmark/converter.rb:38
require "academic_benchmarks"
module AcademicBenchmark
class Converter < Canvas::Migration::Migrator
def initialize(settings = {})
super(settings, "academic_benchmark")
@ratings_overrides = settings[:migration_options] || {}
@course[:learning_outcomes] = []
@partner_id = settings[:partner_id]
@partner_key = settings[:partner_key]
end
def export
unless content_migration
raise Canvas::Migration::Error,
"Missing required content_migration settings"
end
unless Account.site_admin.grants_right?(content_migration.user, :manage_global_outcomes)
raise Canvas::Migration::Error,
"User isn't allowed to edit global outcomes"
end
unless @archive_file
unless @partner_id.present? || AcademicBenchmark.ensure_partner_id.nil?
raise Canvas::Migration::Error, I18n.t("A partner ID is required to use Academic Benchmarks")
end
unless @partner_key.present? || AcademicBenchmark.ensure_partner_key.nil?
raise Canvas::Migration::Error, I18n.t("A partner key is required to use Academic Benchmarks")
end
end
if outcome_data.present?
if outcome_data.instance_of? AcademicBenchmarks::Standards::StandardsForest
outcome_data.trees.each do |t|
@course[:learning_outcomes] << t.root.build_outcomes(@ratings_overrides)
end
else
@course[:learning_outcomes] << outcome_data.root.build_outcomes(@ratings_overrides)
endView on GitHub (pinned to 1c9f0bb801)