{"record":{"id":"070993dca2f5c9a5","repo":"instructure/canvas-lms","slug":"cannot-move-type-display-sis-id-because-it-has-item-type-in","errorCode":null,"errorMessage":"Cannot move #{type_display} #{sis_id} because it has #{item_type} in it.","messagePattern":"Cannot move #(.+?) #(.+?) because it has #(.+?) in it\\.","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/group_category_importer.rb","lineNumber":87,"sourceCode":"          context = @courses_cache[course_id]\n          context ||= @root_account.all_courses.active.find_by(sis_source_id: course_id)\n          raise ImportError, \"Course with id \\\"#{course_id}\\\" didn't exist for #{type_display} #{sis_id}\" unless context\n\n          @courses_cache[context.sis_source_id] = context\n        elsif course_id.nil? && type_display == \"differentiation tag set\"\n          raise ImportError, \"No course_id given for #{type_display} #{sis_id}\"\n        end\n\n        context || @root_account\n      end\n\n      def check_context_movement(category, context, sis_id, type_display)\n        if category && category.groups.active.exists? &&\n           !(context.id == category.context_id && context.class.base_class.name == category.context_type)\n\n          item_type = type_display.include?(\"tag\") ? \"tags\" : \"groups\"\n\n          raise ImportError, \"Cannot move #{type_display} #{sis_id} because it has #{item_type} in it.\"\n        end\n      end\n\n      def apply_status(category, status)\n        case status\n        when /active/i\n          category.deleted_at = nil\n        when /deleted/i\n          category.deleted_at = Time.zone.now\n        end\n      end\n\n      def save_category(category, sis_id, type_display)\n        if category.save\n          data = build_data(category)\n          @roll_back_data << data if data\n          @success_count += 1\n          true","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/group_category_importer.rb#L69-L105","documentation":"check_context_movement guards against moving a group category / differentiation tag set to a different context while it still contains active groups (or tags). Such a move would orphan or mis-scope the child groups, so the importer raises ImportError instead of silently relocating them.","triggerScenarios":"add_group_category / add_differentiation_tag_set imports a sis_id that already exists (category.groups.active.exists?) but whose context_id/context_type differs from the resolved context of the current row — e.g., the row now names a different course or account.","commonSituations":"Changing a category's course_id or account_id in the CSV after groups were created inside it; re-parenting a tag set to another course while it still has tags; merged/re-imported CSVs where the same sis_id maps to two different courses.","solutions":["Delete the active groups/tags in the category first (or import their deletion), then move the category.","Keep the category's context (account_id/course_id) unchanged in the CSV if it already exists with groups.","Use a new sis_id for the category in the new context instead of moving the existing one.","Manually move groups in the UI/API before changing the category's context in SIS."],"exampleFix":"// before (category gc-1 has groups, moving from COURSE-42 to COURSE-7)\ngc-1,Math Groups,,COURSE-7,active\n// after (keep original context, or delete groups first)\ngc-1,Math Groups,,COURSE-42,active","handlingStrategy":"validation","validationCode":"if category && category.groups.active.exists?\n  moving = category.context_id != context.id ||\n           category.context_type != context.class.base_class.name\n  raise ArgumentError, \"cannot move #{category.sis_source_id}: it still has active groups\" if moving\nend","typeGuard":null,"tryCatchPattern":"begin\n  importer.add_group_category(sis_id, acct_id, course_id, name, status)\nrescue SIS::GroupCategoryImporter::ImportError => e\n  if e.message =~ /Cannot move/ then flag_for_manual_review(sis_id)\n  else raise end\nend","preventionTips":["Treat a category's context as immutable once groups exist under it","Delete or move child groups before changing the category's account/course","Diff each import against prior state to spot context changes for existing sis_ids"],"tags":["sis","csv-import","state-conflict","referential-integrity"],"backgroundTag":"invalid-state-transition","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"}