instructure/canvas-lms · error · RuntimeError

set the collection owner first

Error message

set the collection owner first

What it means

MasterCourses::CollectionRestrictor extends the blueprint course restrictor to collections whose owner is a separate model (e.g. AssessmentQuestion banks). restrict_columns requires that the collection owner association was declared beforehand via set_collection_owner_association; without it the pseudocolumn changes cannot be forwarded to the owner class, so it raises immediately.

Solutions

  1. Call set_collection_owner_association (with the owner association symbol) before any restrict_columns call in the model
  2. Ensure the included-hook order puts the association declaration above restrict_columns calls
  3. Compare with an existing restrictor model (e.g. AssessmentQuestion) to copy the correct setup

Example fix

# before
included do
  restrict_columns(:content, [...])
end
# after
included do
  set_collection_owner_association :assessment_question
  restrict_columns(:content, [...])
end
Defensive patterns

Strategy: validation

Validate before calling

raise 'owner not set' unless Model.reflections.key?(Model.collection_owner_association.to_s) # run in an initializer/spec check before restrict_columns

Type guard

def collection_restrictor_configured?(klass)
  klass.respond_to?(:collection_owner_association) && !!klass.collection_owner_association
end

Prevention

When it happens

Trigger: Calling klass.restrict_columns(edit_type, columns) on a model that includes MasterCourses::CollectionRestrictor before calling set_collection_owner_association (e.g. in a model's included block ordering issue).

Common situations: Adding the restrictor to a new model and forgetting the owner association declaration; refactoring model concerns so restrict_columns runs before the association is set; copy-pasting restrictor setup from another model without its owner declaration.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at app/models/master_courses/collection_restrictor.rb:39

  # this is super similar to the normal Restrictor - the main difference is that these models are locked by some parent object
  # e.g. this is a quiz question locked by a quiz
  # even though they do a lot of the same things, i couldn't figure out a way to keep them together that didn't make things super convoluted

  # FYI you'll have to directly hook code that replicates the behavior of
  # `check_before_overwriting_child_content_on_import` into the respective importers if you add this to new objects

  def self.included(klass)
    klass.include MasterCourses::Restrictor::CommonMethods
    klass.extend ClassMethods

    klass.cattr_accessor :collection_owner_association # this is the association to find the quiz

    klass.after_update :mark_downstream_changes, if: -> { klass != Lti::LineItem || Account.site_admin.feature_enabled?(:blueprint_line_item_support) }
  end

  module ClassMethods
    def restrict_columns(edit_type, columns)
      raise "set the collection owner first" unless collection_owner_association

      super
      owner_class = reflections[collection_owner_association.to_s].klass
      owner_class.restrict_columns(edit_type, pseudocolumn_for_type(edit_type)) # e.g. add "assessment_questions_content" as a restricted column
    end

    def pseudocolumn_for_type(type) # prepend with table name because it looks better than "Quizzes::QuizQuestion"
      "#{table_name}_#{type}"
    end
  end

  def check_restrictions?
    true
  end

  def owner_for_restrictions
    send(self.class.base_class.collection_owner_association)
  end

View on GitHub (pinned to 1c9f0bb801)