{"record":{"id":"e9c4321e2f2e2384","repo":"instructure/canvas-lms","slug":"a-templated-course-did-not-pass-validation-course-course-id","errorCode":null,"errorMessage":"A (templated) course did not pass validation (course: #{course_id} / #{short_name}, error: #{templated_course.errors.full_messages.join(\",\")})","messagePattern":"A \\(templated\\) course did not pass validation \\(course: #(.+?) / #(.+?), error: #(.+?)\\)","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/course_importer.rb","lineNumber":243,"sourceCode":"              templated_course.name = course.name if !templated_course.stuck_sis_fields.include?(:name) && !course_name_stuck\n              templated_course.course_code = course.course_code if !templated_course.stuck_sis_fields.include?(:course_code) && !course_course_code_stuck\n              templated_course.enrollment_term = course.enrollment_term if !templated_course.stuck_sis_fields.include?(:enrollment_term_id) && !course_enrollment_term_id_stuck\n              if !templated_course.stuck_sis_fields.intersect?(%i[start_at conclude_at restrict_enrollments_to_course_dates]) && !course_dates_stuck\n                templated_course.start_at = course.start_at\n                templated_course.conclude_at = course.conclude_at\n                templated_course.restrict_enrollments_to_course_dates = course.restrict_enrollments_to_course_dates\n              end\n              templated_course.sis_batch_id = @batch.id\n              @course_ids_to_update_associations.add(templated_course.id) if templated_course.account_id_changed? || templated_course.root_account_id_changed?\n              if templated_course.valid?\n                changes = templated_course.changes\n                templated_course.save_without_broadcasting!\n                Auditors::Course.record_updated(templated_course, @batch_user, changes, source: :sis, sis_batch_id: @batch_id)\n              else\n                msg = \"A (templated) course did not pass validation \" \\\n                      \"(course: #{course_id} / #{short_name}, error: \" \\\n                      \"#{templated_course.errors.full_messages.join(\",\")})\"\n                raise ImportError, msg\n              end\n            end\n            course.sis_batch_id = @batch.id\n            if course.valid?\n              course_changes = course.changes\n              course.save_without_broadcasting!\n              auditor_state_changes(course, state_changes, course_changes)\n              data = SisBatchRollBackData.build_data(sis_batch: @batch, context: course)\n              @roll_back_data << data if data\n            else\n              msg = \"A course did not pass validation \" \\\n                    \"(course: #{course_id} / #{short_name}, error: \" \\\n                    \"#{course.errors.full_messages.join(\",\")})\"\n              raise ImportError, msg\n            end\n            @course_ids_to_update_associations.add(course.id) if update_account_associations\n          else\n            @courses_to_update_sis_batch_id << course.id","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/course_importer.rb#L225-L261","documentation":"SisCourseImporter#add_course raises ImportError when a templated (blueprint/linked) course fails ActiveRecord validation before save_without_broadcasting!. The message includes course_id, short_name, and the concatenated validation errors from templated_course.errors.full_messages, so the real cause is in the embedded error list.","triggerScenarios":"add_course path where the course is a blueprint/templated course and templated_course.valid? fails after applying SIS changes (e.g. invalid name length, invalid dates, constraint violations on the child/templated course object).","commonSituations":"Blueprint course structures where the master course was modified outside SIS making child updates invalid; name/title exceeding column or validation limits; changes conflicting with master-course restrictions; data from the CSV violating model validations only visible on the templated copy.","solutions":["Read the embedded errors.full_messages in the message to identify the exact failed validation","Fix the offending course attribute in courses.csv (name length, dates, format) and re-import","Check whether the blueprint/master course was altered in the UI in a way that now blocks SIS updates; reconcile it first","Update Canvas if a model validation regression is rejecting previously valid SIS data"],"exampleFix":"// before: message shows errors like \"Name is too long\" for a 300-char name\nshort_name = very_long_exported_code\n// after\nshort_name = very_long_exported_code[0, 255]","handlingStrategy":"try-catch","validationCode":"msg = e.message\nif (errs = msg[/error: (.*)\\)$/, 1])\n  log.error(\"templated course validation failed: #{errs}\")\nend","typeGuard":"nil","tryCatchPattern":"begin\n  importer.add_course(...)\nrescue SisImport::ImportError => e\n  raise unless e.message.start_with?('A (templated) course did not pass validation')\n  sis_batch_errors.record(course_id, e.message) # surface embedded errors.full_messages to data owners\nend","preventionTips":["Parse and forward the embedded errors.full_messages to whoever owns the data","Keep blueprint/master courses consistent with SIS-managed attributes","Respect name/field length limits when generating CSV values","Reconcile UI-side blueprint edits with SIS data before large batches"],"tags":["sis-import","validation","blueprint-course"],"backgroundTag":"schema-validation-failed","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"}