{"record":{"id":"5bf099b63ba9b5f1","repo":"instructure/canvas-lms","slug":"cannot-start-new-migration-while-another-one-is-running","errorCode":null,"errorMessage":"cannot start new migration while another one is running","messagePattern":"cannot start new migration while another one is running","errorType":"exception","errorClass":"MigrationRunningError","httpStatus":null,"severity":"warning","filePath":"app/models/master_courses/master_migration.rb","lineNumber":76,"sourceCode":"\n    state :completed # after all the imports have run (successfully hopefully)\n    state :exports_failed # if we break during export\n    state :imports_failed # if one or more of the imports failed\n  end\n\n  class MigrationRunningError < StandardError; end\n\n  # create a new migration and queue it up (if we can)\n  def self.start_new_migration!(master_template, user, opts = {})\n    master_template.class.transaction do\n      master_template.lock!\n      if master_template.active_migration_running?\n        if opts[:retry_later]\n          delay(singleton: \"retry_start_master_migration_#{master_template.global_id}\",\n                run_at: 10.minutes.from_now)\n            .start_new_migration!(master_template, user, opts)\n        else\n          raise MigrationRunningError, \"cannot start new migration while another one is running\"\n        end\n      else\n        new_migration = master_template.master_migrations.create!({ user: }.merge(opts.except(:retry_later, :priority)))\n        master_template.active_migration = new_migration\n        master_template.save!\n        new_migration.queue_export_job(priority: opts[:priority] || Delayed::LOW_PRIORITY)\n        new_migration\n      end\n    end\n  end\n\n  def copy_settings=(val)\n    migration_settings[:copy_settings] = val\n  end\n\n  def send_item_notifications=(val)\n    migration_settings[:send_item_notifications] = val\n  end","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/master_courses/master_migration.rb#L58-L94","documentation":"MasterCourses::MasterMigration.start_new_migration! checks master_template.active_migration_running?; if a migration is already in progress and opts[:retry_later] is not set, it raises MigrationRunningError with this message. Canvas allows only one active master-course migration per template at a time.","triggerScenarios":"Calling start_new_migration! (or triggering an export/sync via API or UI) while the template's previous migration is still queued/running, without passing retry_later: true.","commonSituations":"Users clicking 'sync' repeatedly while a large migration runs; scheduled/automated sync jobs overlapping manual migrations; a stuck previous migration (failed delayed job) that never cleared active_migration, blocking all new ones.","solutions":["Pass retry_later: true so Canvas reschedules the migration in 10 minutes instead of raising.","Wait for the current migration to finish before starting a new one (check master_template.active_migration_running?).","If the active migration is genuinely stuck, clear the stale state (reset master_template.active_migration / inspect the delayed job) and retry.","Debounce/dedupe UI or API triggers so concurrent sync requests don't pile up."],"exampleFix":"// before\nMasterCourses::MasterMigration.start_new_migration!(template, user)\n// after\nMasterCourses::MasterMigration.start_new_migration!(template, user, retry_later: true)","handlingStrategy":"try-catch","validationCode":"if template.active_migration_running?\n  MasterCourses::MasterMigration.start_new_migration!(template, user, retry_later: true)\nelse\n  MasterCourses::MasterMigration.start_new_migration!(template, user)\nend","typeGuard":null,"tryCatchPattern":"begin\n  MasterCourses::MasterMigration.start_new_migration!(template, user)\nrescue MasterCourses::MasterMigration::MigrationRunningError\n  # notify user a migration is already running; retry later\nend","preventionTips":["Default to retry_later: true for automated/scheduled syncs","Check active_migration_running? before exposing the sync button","Monitor for stuck migrations and alert on templates with long-running active_migration"],"tags":["ruby","master-courses","concurrency","state-conflict"],"backgroundTag":"invalid-state-transition","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"}