instructure/canvas-lms · error
No migration file found
Error message
No migration file found
What it means
Canvas migration Archive expects a source file: either a downloaded archive from a provided URL, a local path, or an attachment id in settings. download_archive raises 'No migration file found' when none of these sources yield a file — i.e. @settings has no attachment_id, no archive/file, and no downloadable URL.
Solutions
- Include a valid source in migration settings: archive file bytes, a correct :attachment_id, or a downloadable archive URL
- Verify the attachment_id exists: Attachment.where(id: settings[:attachment_id]).exists?
- Check the migration job's settings serialization hasn't dropped the file keys
- Log settings keys before constructing Archive to spot the missing source
Example fix
// before
Canvas::Migration::Archive.new({migration_id: 5}) # no source
// after
Canvas::Migration::Archive.new({attachment_id: attachment.id}) Defensive patterns
Strategy: validation
Validate before calling
src = settings[:attachment_id] || settings[:archive] || settings[:archive_url] raise 'migration archive source required' if src.blank?
Try / catch
begin archive.download_archive rescue RuntimeError => e raise unless e.message == 'No migration file found' migration.workflow_state = :failed migration.add_warning(:missing_file, 'No source file provided') end
Prevention
- Validate migration settings at the API boundary before queueing jobs
- Confirm the referenced attachment still exists at job start
- Serialize settings so file references survive job persistence
When it happens
Trigger: Creating Canvas::Migration::Archive with settings containing neither archive data, a resolvable URL, nor :attachment_id, then calling download_archive (or any content-import flow reaching it).
Common situations: API content migrations posted without the file/attachment_id parameter; the attachment was deleted between queueing and running the migration; caller passed the wrong settings keys.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Cannot validate existence for resource type: #
- course hasn't been converted
- Course not found
- Embed not found for resource type: #
- Embed not found in scan for resource: #
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/9e5866cf03775791.
Report an issue: GitHub.
Appendix: source
Thrown at lib/canvas/migration/archive.rb:106
if @settings[:export_archive_path]
File.open(@settings[:export_archive_path], "rb")
elsif @settings[:course_archive_download_url].present?
_, uri = CanvasHttp.validate_url(@settings[:course_archive_download_url], check_host: true)
InstrumentTLSCiphers.without_tls_metrics do
CanvasHttp.get(@settings[:course_archive_download_url]) do |http_response|
raise CanvasHttp::InvalidResponseCodeError, http_response.code.to_i unless http_response.code.to_i == 200
tmpfile = CanvasHttp.tempfile_for_uri(uri)
http_response.read_body(tmpfile)
tmpfile.rewind
return tmpfile
end
end
elsif @settings[:attachment_id]
att = Attachment.find(@settings[:attachment_id])
att.open(temp_folder: config[:data_folder])
else
raise "No migration file found"
end
end
delegate :path, to: :file
def unzipped_file_path
unless @unzipped_file_path
config = ConfigFile.load("external_migration") || {}
@unzipped_file_path = Dir.mktmpdir(nil, config[:data_folder].presence)
end
@unzipped_file_path
end
def package_root
@package_root ||= PackageRoot.new(unzipped_file_path)
end
def get_converterView on GitHub (pinned to 1c9f0bb801)