{"record":{"id":"0f5e1a81f6e4f9ab","repo":"instructure/canvas-lms","slug":"no-section-id-given-for-a-cross-listing","errorCode":null,"errorMessage":"No section_id given for a cross-listing","messagePattern":"No section_id given for a cross-listing","errorType":"validation","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/xlist_importer.rb","lineNumber":54,"sourceCode":"      importer.success_count\n    end\n\n    class Work\n      attr_accessor :success_count, :course_ids_to_update_associations\n\n      def initialize(batch, root_account, logger)\n        @batch = batch\n        @root_account = root_account\n        @logger = logger\n        @success_count = 0\n\n        @course = nil\n        @course_ids_to_update_associations = [].to_set\n      end\n\n      def add_crosslist(xlist_course_id, section_id, status)\n        raise ImportError, \"No xlist_course_id given for a cross-listing\" if xlist_course_id.blank?\n        raise ImportError, \"No section_id given for a cross-listing\" if section_id.blank?\n        raise ImportError, \"Improper status \\\"#{status}\\\" for a cross-listing\" unless /\\A(active|deleted)\\z/i.match?(status)\n        return if @batch.skip_deletes? && status =~ /deleted/i\n\n        section = @root_account.course_sections.find_by(sis_source_id: section_id)\n        raise ImportError, \"A cross-listing referenced a non-existent section #{section_id}\" unless section\n\n        unless @course && @course.sis_source_id == xlist_course_id\n          @course = @root_account.all_courses.find_by(sis_source_id: xlist_course_id)\n          if !@course && status =~ /\\Aactive\\z/i\n            # no course with this crosslist id found, make a new course,\n            # using the section's current course as a template\n            @course = Course.new\n            @course.root_account = @root_account\n            @course.account_id = section.course.account_id\n            @course.name = section.course.name\n            @course.course_code = section.course.course_code\n            @course.enrollment_term_id = section.course.enrollment_term_id\n            @course.start_at = section.course.start_at","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/xlist_importer.rb#L36-L72","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nxlist.add_crosslist(row['course_id'], row['section_id'], row['status'])\n# after\nif row['section_id'].blank?\n  @logger.warn(\"Skipping crosslist row #{row}: missing section_id\")\nelse\n  xlist.add_crosslist(row['course_id'], row['section_id'], row['status'])\nend","handlingStrategy":"validation","validationCode":"raise 'section_id required' if section_id.blank?\nxlist.add_crosslist(xlist_course_id, section_id, status)","typeGuard":null,"tryCatchPattern":"begin\n  xlist.add_crosslist(xlist_course_id, section_id, status)\nrescue SIS::ImportError => e\n  Rails.logger.warn(\"Crosslist row skipped: #{e.message}\")\nend","preventionTips":["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"],"tags":["sis","import","missing-argument","cross-listing"],"backgroundTag":"missing-required-argument","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"}