{"record":{"id":"582f0f3531879d8a","repo":"instructure/canvas-lms","slug":"improper-status-status-for-a-cross-listing","errorCode":null,"errorMessage":"Improper status \"#{status}\" for a cross-listing","messagePattern":"Improper status \"#(.+?)\" for a cross-listing","errorType":"validation","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/xlist_importer.rb","lineNumber":55,"sourceCode":"    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\n            @course.conclude_at = section.course.conclude_at","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/xlist_importer.rb#L37-L73","documentation":"The SIS cross-listing importer validates that each row's status is exactly 'active' or 'deleted' (case-insensitive) and raises ImportError for anything else. The status drives whether the section is cross-listed into the target course or uncross-listed, so unknown values are rejected before any data is touched.","triggerScenarios":"Calling add_crosslist(xlist_course_id, section_id, status) where status is not /\\A(active|deleted)\\z/i — e.g. 'delete', 'Active ', 'enabled', or a nil status from a blank CSV cell. Note the second guard at line 121 also catches statuses that pass initial regex checks only if the regex changed; normally this fires for unexpected case values hitting the case statement.","commonSituations":"Hand-edited SIS CSVs using synonyms like 'remove' or 'deactivate'; integrations sending boolean-ish values ('true'/'false'); locale-transformed exports; trailing whitespace or BOM characters contaminating the status column.","solutions":["Use only 'active' or 'deleted' as status values in the crosslist SIS file","Strip whitespace and normalize casing of the status column before import","Map third-party status vocabulary to active/deleted before calling add_crosslist","Add a pre-import CSV lint that rejects rows with statuses outside the allowed set"],"exampleFix":"# before\nxlist.add_crosslist(course_id, section_id, row['status']) # \"remove\"\n# after\nstatus = row['status'].to_s.strip.downcase\nstatus = 'deleted' if status == 'remove'\nxlist.add_crosslist(course_id, section_id, status)","handlingStrategy":"validation","validationCode":"unless status.to_s.match?(/\\A(active|deleted)\\z/i)\n  raise ArgumentError, \"status must be active or deleted, got #{status.inspect}\"\nend","typeGuard":null,"tryCatchPattern":"begin\n  xlist.add_crosslist(xlist_course_id, section_id, status)\nrescue SIS::ImportError => e\n  Rails.logger.warn(\"Bad crosslist status: #{e.message}\")\nend","preventionTips":["Whitelist statuses to active/deleted at the CSV parsing layer","Normalize casing/whitespace before calling add_crosslist","Map upstream SIS status vocabulary explicitly","Add a lint step for crosslist.csv in CI"],"tags":["sis","import","invalid-enum-value","cross-listing"],"backgroundTag":"invalid-enum-value","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"}