instructure/canvas-lms · error

Course pace is not deleted

Error message

Course pace is not deleted

What it means

CoursePace#republish_paces_for_affected_enrollments reassigns enrollments to remaining published paces after a pace is deleted; it is only valid on a deleted pace, so it raises when called on a pace that is not deleted.

Solutions

  1. Only call this after successfully deleting the pace (guard with pace.deleted?).
  2. Ensure the deletion transaction committed before enqueueing the republish job.
  3. If the pace was restored, republish via publish instead of this cleanup method.

Example fix

// before
pace.republish_paces_for_affected_enrollments

// after
pace.destroy_or_delete_with_enrollment_republish # or:
pace.reload
pace.republish_paces_for_affected_enrollments if pace.deleted?
Defensive patterns

Strategy: validation

Validate before calling

raise 'pace not deleted' unless course_pace.reload.deleted?

Type guard

republishable = ->(p) { p.reload.deleted? }

Prevention

When it happens

Trigger: Calling course_pace.republish_paces_for_affected_enrollments on an active or unpublished pace; invoking it manually (or via job) instead of through the deletion workflow.

Common situations: Retrying a cleanup job whose target pace was already processed/restored; calling the method out of order in custom deletion flows; re-running jobs after a pace was un-deleted.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at app/models/course_pace.rb:245

      # Clear caches
      Assignment.clear_cache_keys(assignments_to_refresh, :availability)
      SubmissionLifecycleManager.recompute_course(course, assignments: assignments_to_refresh, update_grades: true)

      # Maintain the weights of the module items
      course_pace_module_items.each(&:restore_attributes)

      # Explicitly complete the progress so we aren't left with any hanging progresses
      progress.complete! if progress&.running?

      # Mark as published
      log_module_items_count
      update(workflow_state: "active", published_at: Time.zone.now)
    end
  end

  def republish_paces_for_affected_enrollments
    raise "Course pace is not deleted" unless deleted?

    grouped_paces_and_enrollments = student_enrollments.group_by do |enrollment|
      student_section_ids = enrollment.user.student_enrollments.shard(shard).where(course:).active.pluck(:course_section_id)
      pace = course.course_paces.published.where(course_section_id: student_section_ids).last
      pace || course.course_paces.published.primary.take
    end
    grouped_paces_and_enrollments.each do |pace, enrollments|
      pace.create_publish_progress(enrollment_ids: enrollments.pluck(:id))
    end
  end

  def published?
    active?
  end

  def primary?
    !deleted? && course_section_id.nil? && user_id.nil?
  end

View on GitHub (pinned to 1c9f0bb801)