instructure/canvas-lms · error · Delayed::RetriableError

e.message

Error message

e.message

What it means

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.

Solutions

  1. Inspect cm.migration_settings[:last_error] and the Delayed::RetriableError message for the root cause
  2. Verify InstFS service health (service.up? / inst-fs logs) if the message is a ServiceError
  3. Fix invalid migration settings/context causing RecordInvalid, then re-run the copy
  4. Let the job retry; if retries exhaust, re-queue the course copy from the UI

Example fix

// before (caller triggering copy)
course_copy = course.content_migrations.build(migration_type: 'course_copy_importer')
course_copy.save!
// after
begin
  course_copy.save!
rescue ActiveRecord::RecordInvalid => e
  Rails.logger.error("course copy failed to start: #{e.message}")
end
Defensive patterns

Strategy: retry

Try / catch

begin
  course_copy.run
rescue Delayed::RetriableError => e
  Rails.logger.warn("course copy retrying: #{e.message}")
  check_last_error(course_copy)
end

Prevention

When it happens

Trigger: 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.

Common situations: InstFS outage/timeouts during export, record validation failure from bad migration_settings, shard/context misconfiguration, transient DB issues during job execution.

Related errors


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

Appendix: source

Thrown at lib/canvas/migration/worker/course_copy_worker.rb:79

          cm.copy_attachments_for_migration(ce)
          cm.update_import_progress(20)

          cm.import_content
          SmartSearch.copy_embeddings(cm)

          cm.workflow_state = :imported
          cm.save
          cm.update_import_progress(100)
        end
      else
        cm.workflow_state = :failed
        cm.migration_settings[:last_error] = "ContentExport failed to export course."
        cm.save
      end
    rescue InstFS::ServiceError, ::ActiveRecord::RecordInvalid => e
      Canvas::Errors.capture_exception(:course_copy, e, :warn)
      cm.fail_with_error!(e)
      raise Delayed::RetriableError, e.message
    rescue => e
      cm.fail_with_error!(e)
      raise e
    end
  end

  def find_suitable_content_export(source, cm)
    return unless cm.for_course_template?

    candidate_exports = source.content_exports
                              .where(export_type: ContentExport::COURSE_TEMPLATE_COPY,
                                     workflow_state: "exported_for_course_copy",
                                     created_at: source.updated_at..,
                                     user_id: nil)
                              .order(id: :desc)
                              .limit(5)
                              .to_a
    candidate_exports.find { |ce| !ce.expired? && ce.selected_content.key?("attachments") }

View on GitHub (pinned to 1c9f0bb801)