instructure/canvas-lms · error

unsupported migration type

Error message

unsupported migration type

What it means

selective_content_formatter#get_content_list serves the list of migratable items per content type (assignments, quizzes, modules, etc.). It raises 'unsupported migration type' when the requested type is neither one of SELECTIVE_CONTENT_TYPES, nor a 'submodules_'/'learning_outcome_groups_' prefixed type, nor nil.

Solutions

  1. Check SELECTIVE_CONTENT_TYPES in selective_content_formatter.rb for the accepted type strings
  2. Fix the caller to pass one of the supported types (or omit type for all)
  3. Add the new type to SELECTIVE_CONTENT_TYPES if it is a legitimately new content category
  4. Guard API clients against version skew by validating types against the course migration's available types

Example fix

// before
formatter.get_content_list("wiki_pages_old")
// after
formatter.get_content_list("wiki_pages")
Defensive patterns

Strategy: validation

Validate before calling

SELECTIVE_CONTENT_TYPES = %w[assignments quizzes modules files pages discussions announcements].freeze
raise 'bad type' unless type.nil? || SELECTIVE_CONTENT_TYPES.include?(type)

Type guard

def supported_type?(t)
  t.nil? || SELECTIVE_CONTENT_TYPES.include?(t) || t.start_with?('submodules_', 'learning_outcome_groups_')
end

Try / catch

begin
  formatter.get_content_list(type)
rescue RuntimeError => e
  raise unless e.message == 'unsupported migration type'
  render json: {error: 'unsupported type'}, status: :bad_request
end

Prevention

When it happens

Trigger: Calling get_content_list('unknown_type') (optionally with source) on a SelectiveContentFormatter where valid_type? returns false — e.g. an arbitrary type string from an API client or a typo'd content type.

Common situations: Frontend/API sending a content type the backend version doesn't know (version skew); new content types added in one layer but not to SELECTIVE_CONTENT_TYPES; hand-crafted API requests.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at lib/canvas/migration/helpers/selective_content_formatter.rb:54

      ["calendar_events", -> { I18n.t("lib.canvas.migration.calendar_events", "Calendar Events") }],
      ["rubrics", -> { I18n.t("lib.canvas.migration.rubrics", "Rubrics") }],
      ["groups", -> { I18n.t("lib.canvas.migration.groups", "Student Groups") }],
      ["learning_outcomes", -> { I18n.t("lib.canvas.migration.learning_outcomes", "Learning Outcomes") }],
      ["attachments", -> { I18n.t("lib.canvas.migration.attachments", "Files") }],
    ].freeze

    def initialize(migration = nil, base_url = nil, global_identifiers:)
      @migration = migration
      @base_url = base_url
      @global_identifiers = global_identifiers
    end

    def valid_type?(type = nil)
      type.nil? || SELECTIVE_CONTENT_TYPES.any? { |t| t[0] == type } || type.start_with?("submodules_") || type.start_with?("learning_outcome_groups_")
    end

    def get_content_list(type = nil, source = nil)
      raise "unsupported migration type" unless valid_type?(type)

      if !@migration || @migration.migration_type == "course_copy_importer"
        get_content_from_course(type, source)
      elsif @migration.overview_attachment
        get_content_from_overview(type)
      else
        raise "course hasn't been converted"
      end
    end

    private

    def property_prefix
      @migration ? "copy" : "select"
    end

    # pulls the available items from the overview attachment on the content migration
    def get_content_from_overview(type = nil)

View on GitHub (pinned to 1c9f0bb801)