{"record":{"id":"9e5866cf03775791","repo":"instructure/canvas-lms","slug":"no-migration-file-found","errorCode":null,"errorMessage":"No migration file found","messagePattern":"No migration file found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/canvas/migration/archive.rb","lineNumber":106,"sourceCode":"      if @settings[:export_archive_path]\n        File.open(@settings[:export_archive_path], \"rb\")\n      elsif @settings[:course_archive_download_url].present?\n        _, uri = CanvasHttp.validate_url(@settings[:course_archive_download_url], check_host: true)\n        InstrumentTLSCiphers.without_tls_metrics do\n          CanvasHttp.get(@settings[:course_archive_download_url]) do |http_response|\n            raise CanvasHttp::InvalidResponseCodeError, http_response.code.to_i unless http_response.code.to_i == 200\n\n            tmpfile = CanvasHttp.tempfile_for_uri(uri)\n            http_response.read_body(tmpfile)\n            tmpfile.rewind\n            return tmpfile\n          end\n        end\n      elsif @settings[:attachment_id]\n        att = Attachment.find(@settings[:attachment_id])\n        att.open(temp_folder: config[:data_folder])\n      else\n        raise \"No migration file found\"\n      end\n    end\n\n    delegate :path, to: :file\n\n    def unzipped_file_path\n      unless @unzipped_file_path\n        config = ConfigFile.load(\"external_migration\") || {}\n        @unzipped_file_path = Dir.mktmpdir(nil, config[:data_folder].presence)\n      end\n      @unzipped_file_path\n    end\n\n    def package_root\n      @package_root ||= PackageRoot.new(unzipped_file_path)\n    end\n\n    def get_converter","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/canvas/migration/archive.rb#L88-L124","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nCanvas::Migration::Archive.new({migration_id: 5}) # no source\n// after\nCanvas::Migration::Archive.new({attachment_id: attachment.id})","handlingStrategy":"validation","validationCode":"src = settings[:attachment_id] || settings[:archive] || settings[:archive_url]\nraise 'migration archive source required' if src.blank?","typeGuard":null,"tryCatchPattern":"begin\n  archive.download_archive\nrescue RuntimeError => e\n  raise unless e.message == 'No migration file found'\n  migration.workflow_state = :failed\n  migration.add_warning(:missing_file, 'No source file provided')\nend","preventionTips":["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"],"tags":["ruby","migration","content-import","missing-input"],"backgroundTag":"missing-required-argument","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}