instructure/canvas-lms · error · ImportError
Improper status "# " for an enrollment
Error message
Improper status "#{enrollment.status}" for an enrollment What it means
EnrollmentImporter.add_enrollment raises ImportError when `enrollment.valid_status?` is false, i.e. the enrollment status is not one of the accepted values (active, deleted, completed, inactive and variants, case-insensitive). The interpolated status is included in the message to show the offending value.
Solutions
- Map source statuses to Canvas-accepted values: active, deleted, completed, inactive (case-insensitive)
- Trim/normalize the status string before constructing the Enrollment
- Add a preprocessing step that translates foreign status vocabularies
- Check the CSV header mapping so the status column is parsed correctly
Example fix
// before SIS::Models::Enrollment.new(course_id: 'c1', user_id: 'u1', status: 'enrolled') // after SIS::Models::Enrollment.new(course_id: 'c1', user_id: 'u1', status: 'active')
Defensive patterns
Strategy: validation
Validate before calling
ALLOWED = %w[active deleted completed inactive] raise 'bad status' unless ALLOWED.include?(enrollment.status.to_s.strip.downcase)
Try / catch
begin
importer.add_enrollment(enrollment)
rescue SIS::Base::ImportError => e
logger.warn("Skipping enrollment: #{e.message}")
end Prevention
- Normalize status with strip/downcase before constructing the model
- Map foreign status vocabularies to Canvas values in the export step
- Document accepted statuses for whoever produces the CSV
When it happens
Trigger: Calling `add_enrollment(enrollment)` with a status like 'enrolled', 'ACTIVE ', 'drop', or a typo such as 'actve'; CSV rows with unexpected values in the status/enrollment_state column.
Common situations: Exports from other SIS/LMS systems using their own state vocabularies ('enrolled', 'pending', 'withdrawn'); trailing whitespace or casing assumptions; header mapped to the wrong column (e.g. role instead of status).
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Improper grade_publishing_status "#
- Improper status "# " for institutional tag category #
- No account found for context
- No course_id or section_id given for an enrollment
- No user_id given for an enrollment
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/4a73df0f3f297b53.
Report an issue: GitHub.
Appendix: source
Thrown at lib/sis/enrollment_importer.rb:135
@courses_to_touch_ids = Set.new
@courses_to_recache_due_dates = {}
@enrollments_to_add_to_favorites = []
@enrollments_to_update_sis_batch_ids = []
@roll_back_data = []
@enrollments_to_delete = []
@account_chain_cache = {}
@course = @section = nil
@course_roles_by_account_id = {}
@enrollment_batch = []
@success_count = 0
end
# Pass a single instance of SIS::Models::Enrollment
def add_enrollment(enrollment)
raise ImportError, "No course_id or section_id given for an enrollment" unless enrollment.valid_context?
raise ImportError, "No user_id given for an enrollment" unless enrollment.valid_user?
raise ImportError, "Improper status \"#{enrollment.status}\" for an enrollment" unless enrollment.valid_status?
return if @batch.skip_deletes? && enrollment.status =~ /deleted/i
@enrollment_batch << enrollment
process_batch if @enrollment_batch.size >= BATCH_SIZE
end
def any_left_to_process?
!@enrollment_batch.empty?
end
def process_batch
return unless any_left_to_process?
enrollment_info = nil
until @enrollment_batch.empty?
enrollment_info = @enrollment_batch.shift
@last_section = @section if @sectionView on GitHub (pinned to 1c9f0bb801)