instructure/canvas-lms · error
Needs self.item_class to be set in #
Error message
Needs self.item_class to be set in #{self} What it means
Importers::Importer subclasses forward class-level helpers (translate/t) to their item_class, but only if item_class is set via the class-level accessor. Calling translate on a subclass whose item_class was never assigned raises this RuntimeError naming the offending class, because there is no target to forward the call to.
Solutions
- Add an item_class declaration to the importer class, e.g. item_class 'CalendarEvent', inside the subclass body
- If the class shouldn't forward translations, override translate/logger locally instead of relying on the shared implementation
- Check git history for importer classes that lost their item_class assignment during a refactor
Example fix
// before class Importers::DiscussionTopicImporter < Importers::Importer end // after class Importers::DiscussionTopicImporter < Importers::Importer item_class 'DiscussionTopic' end
Defensive patterns
Strategy: validation
Validate before calling
raise 'importer missing item_class' unless MyImporter.item_class
Type guard
def usable_importer?(klass) klass.is_a?(Class) && klass < Importers::Importer && !klass.item_class.nil? end
Try / catch
begin
importer.translate(payload)
rescue RuntimeError => e
raise unless e.message.start_with?('Needs self.item_class')
Rails.logger.error("misconfigured importer: #{e.message}")
end Prevention
- Always declare item_class immediately when subclassing Importers::Importer
- Add a boot-time check iterating Importers::Importer subclasses asserting item_class is set
- Note it in the importer template/scaffold
When it happens
Trigger: Calling SomeImporter.translate (or .t) on an importer subclass that defines no self.item_class = '...' assignment — typically a newly written or partially ported importer that relies on the inherited translate without registering its item class.
Common situations: Writing a new content importer and forgetting `item_class 'DiscussionTopic'` (or equivalent) in the class body; older importer classes predating the item_class refactor being invoked through the new forwarding path.
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
- No content importer registered for #
- A new_id, '# ', referenced an existing # and the # with #…
- A new_integration_id, '#
- A student referenced a non-existent user #
- an object with an interface for loading settings must be…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/d309dd2c1c4d660f.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/importers.rb:50
def self.disable_live_events!
ActiveRecord::Base.observers.disable LiveEventsObserver
yield
ensure
enable_live_events!
end
def self.enable_live_events!
ActiveRecord::Base.observers.enable LiveEventsObserver
end
class Importer
class << self
attr_accessor :item_class
# forward translations to CalendarEvent; they used to live there.
def translate(*)
raise "Needs self.item_class to be set in #{self}" unless item_class
item_class.translate(*)
end
alias_method :t, :translate
def logger(*)
raise "Needs self.item_class to be set in #{self}" unless item_class
item_class.logger(*)
end
end
end
register_content_importer(AccountContentImporter)
register_content_importer(CourseContentImporter)
end
View on GitHub (pinned to 1c9f0bb801)