instructure/canvas-lms · error · ImportError
A cross-listing referenced a non-existent section #
Error message
A cross-listing referenced a non-existent section #{section_id} What it means
The importer looks up the section by sis_source_id under the root account (CourseSections) and raises ImportError when no section matches. The cross-listing cannot proceed because the target section record does not exist in Canvas yet or its SIS ID differs.
Solutions
- Import the sections (sections.csv) before or in the same batch as crosslist.csv
- Verify the section_id matches the section's sis_source_id exactly (no typos, no stale IDs)
- Confirm the import is running against the correct root_account that contains the section
- Re-run the section import to recreate missing sections, then retry the crosslist import
Example fix
# before (ordering) # crosslist.csv imported standalone # after # import sections.csv first, then crosslist.csv in the same sis batch
Defensive patterns
Strategy: validation
Validate before calling
section = root_account.course_sections.find_by(sis_source_id: section_id)
raise "Section #{section_id} not found; import sections first" unless section Try / catch
begin
xlist.add_crosslist(xlist_course_id, section_id, status)
rescue SIS::ImportError => e
if e.message =~ /non-existent section/
Rails.logger.error("Re-run sections.csv import; missing section #{section_id}")
end
end Prevention
- Always import sections.csv before crosslist.csv in the same batch
- Verify SIS IDs against the source system before export
- Ensure the batch runs against the root account that owns the sections
- Diff SIS IDs between exports to catch renames
When it happens
Trigger: add_crosslist is called with a section_id whose sis_source_id has no matching CourseSection in the root account — the section was never imported, was imported under a different SIS ID, or belongs to a different root account/subaccount.
Common situations: Crosslist.csv processed before sections.csv in the same SIS batch or a previous batch failed; section SIS IDs renamed upstream; importing into the wrong root account; sections deleted in Canvas but still present in the SIS export.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- A deleted cross-listing failed: #
- A student referenced a non-existent user #
- An active cross-listing failed: #
- Can't delete a non-existent observer for observer: #
- Improper status "# " for a cross-listing
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/9ecbb64b87df67a4.
Report an issue: GitHub.
Appendix: source
Thrown at lib/sis/xlist_importer.rb:59
def initialize(batch, root_account, logger)
@batch = batch
@root_account = root_account
@logger = logger
@success_count = 0
@course = nil
@course_ids_to_update_associations = [].to_set
end
def add_crosslist(xlist_course_id, section_id, status)
raise ImportError, "No xlist_course_id given for a cross-listing" if xlist_course_id.blank?
raise ImportError, "No section_id given for a cross-listing" if section_id.blank?
raise ImportError, "Improper status \"#{status}\" for a cross-listing" unless /\A(active|deleted)\z/i.match?(status)
return if @batch.skip_deletes? && status =~ /deleted/i
section = @root_account.course_sections.find_by(sis_source_id: section_id)
raise ImportError, "A cross-listing referenced a non-existent section #{section_id}" unless section
unless @course && @course.sis_source_id == xlist_course_id
@course = @root_account.all_courses.find_by(sis_source_id: xlist_course_id)
if !@course && status =~ /\Aactive\z/i
# no course with this crosslist id found, make a new course,
# using the section's current course as a template
@course = Course.new
@course.root_account = @root_account
@course.account_id = section.course.account_id
@course.name = section.course.name
@course.course_code = section.course.course_code
@course.enrollment_term_id = section.course.enrollment_term_id
@course.start_at = section.course.start_at
@course.conclude_at = section.course.conclude_at
@course.restrict_enrollments_to_course_dates = section.course.restrict_enrollments_to_course_dates
@course.sis_source_id = xlist_course_id
@course.sis_batch_id = @batch.id
@course.workflow_state = "claimed"View on GitHub (pinned to 1c9f0bb801)