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

  1. Run the import with a user holding manage_global_outcomes on Account.site_admin.
  2. Grant the permission via a site-admin role or role override for the service account.
  3. Pre-check with Account.site_admin.grants_right?(cm.user, :manage_global_outcomes) before creating the migration.
  4. 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

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


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)
        end

View on GitHub (pinned to 1c9f0bb801)