instructure/canvas-lms · error · ImportError
No section_id given for a cross-listing
Error message
No section_id given for a cross-listing
What it means
The SIS cross-listing importer raises ImportError when a cross-listing row arrives without a section_id. A cross-listing maps an existing course section to a target course (xlist_course_id), so without the section_id the importer cannot identify which section to move or uncross-list, and it aborts the row before any DB lookup.
Solutions
- Ensure every cross-listing row has a non-blank section_id matching a course section's sis_source_id
- Validate/normalize the SIS CSV before import (skip or fail rows with missing required columns)
- Guard the caller: skip add_crosslist when section_id.blank? and log the row instead
- Check column order/mapping in the CSV template — a shifted column often leaves section_id empty
Example fix
# before
xlist.add_crosslist(row['course_id'], row['section_id'], row['status'])
# after
if row['section_id'].blank?
@logger.warn("Skipping crosslist row #{row}: missing section_id")
else
xlist.add_crosslist(row['course_id'], row['section_id'], row['status'])
end Defensive patterns
Strategy: validation
Validate before calling
raise 'section_id required' if section_id.blank? xlist.add_crosslist(xlist_course_id, section_id, status)
Try / catch
begin
xlist.add_crosslist(xlist_course_id, section_id, status)
rescue SIS::ImportError => e
Rails.logger.warn("Crosslist row skipped: #{e.message}")
end Prevention
- Validate SIS CSV required columns before running the import
- Log and skip rows with blank identifiers instead of failing silently
- Pin the CSV column order in the export template
- Write an import smoke test with an intentionally blank section_id
When it happens
Trigger: Calling SIS::XlistImporter::Work#add_crosslist with a nil/empty string section_id — e.g. a CSV row in the crosslist_file with a blank section_id column, or a plugin/API caller passing only xlist_course_id and status.
Common situations: Malformed or partially filled SIS crosslist.csv exports; columns misaligned after spreadsheet edits; upstream SIS systems emitting empty section identifiers; custom scripts constructing xlist entries programmatically and omitting section_id.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- A cross-listing referenced a non-existent section #
- A deleted cross-listing failed: #
- An active cross-listing failed: #
- Improper status "# " for a cross-listing
- A new_id, '# ', referenced an existing # and the # with #…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/0f5e1a81f6e4f9ab.
Report an issue: GitHub.
Appendix: source
Thrown at lib/sis/xlist_importer.rb:54
importer.success_count
end
class Work
attr_accessor :success_count, :course_ids_to_update_associations
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_atView on GitHub (pinned to 1c9f0bb801)