{"record":{"id":"fbbb4b1ca4c07103","repo":"instructure/canvas-lms","slug":"e-message-course-copy-worker","errorCode":null,"errorMessage":"e.message","messagePattern":"e\\.message","errorType":"exception","errorClass":"Delayed::RetriableError","httpStatus":null,"severity":"error","filePath":"lib/canvas/migration/worker/course_copy_worker.rb","lineNumber":79,"sourceCode":"          cm.copy_attachments_for_migration(ce)\n          cm.update_import_progress(20)\n\n          cm.import_content\n          SmartSearch.copy_embeddings(cm)\n\n          cm.workflow_state = :imported\n          cm.save\n          cm.update_import_progress(100)\n        end\n      else\n        cm.workflow_state = :failed\n        cm.migration_settings[:last_error] = \"ContentExport failed to export course.\"\n        cm.save\n      end\n    rescue InstFS::ServiceError, ::ActiveRecord::RecordInvalid => e\n      Canvas::Errors.capture_exception(:course_copy, e, :warn)\n      cm.fail_with_error!(e)\n      raise Delayed::RetriableError, e.message\n    rescue => e\n      cm.fail_with_error!(e)\n      raise e\n    end\n  end\n\n  def find_suitable_content_export(source, cm)\n    return unless cm.for_course_template?\n\n    candidate_exports = source.content_exports\n                              .where(export_type: ContentExport::COURSE_TEMPLATE_COPY,\n                                     workflow_state: \"exported_for_course_copy\",\n                                     created_at: source.updated_at..,\n                                     user_id: nil)\n                              .order(id: :desc)\n                              .limit(5)\n                              .to_a\n    candidate_exports.find { |ce| !ce.expired? && ce.selected_content.key?(\"attachments\") }","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/canvas/migration/worker/course_copy_worker.rb#L61-L97","documentation":"CourseCopyWorker#perform rescues InstFS::ServiceError and ActiveRecord::RecordInvalid, records the failure on the content migration (fail_with_error!), reports to Canvas::Errors, and re-raises as Delayed::RetriableError with the original message so the delayed job framework retries. It indicates the content export step failed transiently or due to validation.","triggerScenarios":"Running the course copy delayed job when creating the export raises InstFS::ServiceError (inst-fs request failure) or ActiveRecord::RecordInvalid (e.g. invalid cm/attachment state), inside the 'ContentExport failed to export course' branch.","commonSituations":"InstFS outage/timeouts during export, record validation failure from bad migration_settings, shard/context misconfiguration, transient DB issues during job execution.","solutions":["Inspect cm.migration_settings[:last_error] and the Delayed::RetriableError message for the root cause","Verify InstFS service health (service.up? / inst-fs logs) if the message is a ServiceError","Fix invalid migration settings/context causing RecordInvalid, then re-run the copy","Let the job retry; if retries exhaust, re-queue the course copy from the UI"],"exampleFix":"// before (caller triggering copy)\ncourse_copy = course.content_migrations.build(migration_type: 'course_copy_importer')\ncourse_copy.save!\n// after\nbegin\n  course_copy.save!\nrescue ActiveRecord::RecordInvalid => e\n  Rails.logger.error(\"course copy failed to start: #{e.message}\")\nend","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  course_copy.run\nrescue Delayed::RetriableError => e\n  Rails.logger.warn(\"course copy retrying: #{e.message}\")\n  check_last_error(course_copy)\nend","preventionTips":["Monitor InstFS availability before bulk copy jobs","Validate migration settings before enqueueing","Set sensible retry policies on the delayed job queue"],"tags":["content-migration","delayed-job","instfs","active-record"],"backgroundTag":"retryable-job-failed","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"}