instructure/canvas-lms · error · Canvas::Migration::Error

File required for content migration.

Error message

File required for content migration.

What it means

CC::Importer::CCWorker#perform starts a content-migration conversion job. Before instantiating the converter it needs a source package: it looks for an attachment on the ContentMigration, then a file_url to download, and finally honors a no_archive_file escape hatch. If none of the three exist, it raises Canvas::Migration::Error with 'File required for content migration.' because there is no archive to convert.

Solutions

  1. Re-create or re-upload the migration with a valid file attachment (check cm.attachment_id is set before enqueueing).
  2. If migrating by URL, set migration_settings[:file_url] to a reachable archive URL so the worker can download it.
  3. If the migration intentionally has no archive (e.g. copy by source course ID), set migration_settings[:no_archive_file] = true and supply migration_settings[:converter_class].
  4. Inspect the failed ContentMigration's migration_settings to see which of attachment/file_url/no_archive_file was expected but missing.

Example fix

# before
migration = course.content_migrations.create!
migration.migration_settings[:migration_type] = 'canvas_cartridge_importer'
migration.save!
migration.queue_migration

# after
migration = course.content_migrations.create!
migration.attachment = uploaded_zip_attachment
migration.migration_settings[:migration_type] = 'canvas_cartridge_importer'
migration.save!
migration.queue_migration
Defensive patterns

Strategy: validation

Validate before calling

raise 'attachment required' unless cm.attachment || cm.migration_settings[:file_url] || cm.migration_settings[:no_archive_file]
cm.queue_migration

Type guard

def migration_has_source?(cm)
  cm.attachment.present? || cm.migration_settings[:file_url].present? || cm.migration_settings[:no_archive_file] == true
end

Try / catch

begin
  worker.perform(cm)
rescue Canvas::Migration::Error => e
  if e.message.include?("File required")
    cm.fail_with_error!(e)
  else
    raise
  end
end

Prevention

When it happens

Trigger: A ContentMigration is queued with no cm.attachment, no migration_settings[:file_url], and no migration_settings[:no_archive_file] — e.g. an upload request created the migration record but the attachment failed to attach, or an API client kicked off the job without posting the file.

Common situations: Multipart upload dropped the file before the job ran; a course-copy/import API call was made with neither a file nor a source_course; a background job was requeued after the attachment record was deleted; custom integrations calling the imports API without the export_file parameter.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at lib/cc/importer/cc_worker.rb:40

    cm ||= ContentMigration.where(id: migration_id).first
    cm.save if cm.capture_job_id
    cm.job_progress.start unless cm.skip_job_progress
    begin
      cm.update_conversion_progress(1)
      settings = cm.migration_settings.clone
      settings[:content_migration_id] = migration_id
      settings[:user_id] = cm.user_id
      settings[:content_migration] = cm
      settings[:is_discussion_checkpoints_enabled] = discussion_checkpoints_enabled?(cm)

      if cm.attachment
        settings[:attachment_id] = cm.attachment.id
      elsif settings[:file_url]
        # create attachment and download file
        att = Canvas::Migration::Worker.download_attachment(cm, settings[:file_url])
        settings[:attachment_id] = att.id
      elsif !settings[:no_archive_file]
        raise Canvas::Migration::Error, I18n.t(:no_migration_file, "File required for content migration.")
      end

      converter_class = settings[:converter_class]
      unless converter_class
        if settings[:no_archive_file]
          raise ArgumentError, "converter_class required for content migration with no file"
        end

        settings[:archive] = Canvas::Migration::Archive.new(settings)
        converter_class = settings[:archive].get_converter
      end
      converter = converter_class.new(settings)

      course = converter.export
      export_folder_path = course[:export_folder_path]
      overview_file_path = course[:overview_file_path]

      if overview_file_path

View on GitHub (pinned to 1c9f0bb801)