{"record":{"id":"f4e814507e0bd9b8","repo":"instructure/canvas-lms","slug":"cannot-delete-the-sub-account-with-id-account-id-because-it-f4e814","errorCode":null,"errorMessage":"Cannot delete the sub_account with ID: #{account_id} because it has active courses.","messagePattern":"Cannot delete the sub_account with ID: #(.+?) because it has active courses\\.","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/account_importer.rb","lineNumber":91,"sourceCode":"\n        account.root_account = @root_account\n        if account.new_record? || !account.stuck_sis_fields.include?(:parent_account_id) || Account.sis_stickiness_options[:add_sis_stickiness]\n          account.parent_account = parent || @root_account\n        end\n\n        # only update the name on new records, and ones that haven't been changed since the last sis import\n        account.name = name if name.present? && (account.new_record? || !account.stuck_sis_fields.include?(:name))\n\n        account.integration_id = integration_id if integration_id.present?\n        account.sis_source_id = account_id\n\n        if status.present?\n          case status\n          when /active/i\n            account.workflow_state = \"active\"\n          when /deleted/i\n            raise ImportError, \"Cannot delete the sub_account with ID: #{account_id} because it has active sub accounts.\" if account.sub_accounts.active.exists?\n            raise ImportError, \"Cannot delete the sub_account with ID: #{account_id} because it has active courses.\" if account.courses.active.exists?\n\n            account.workflow_state = \"deleted\"\n          end\n        end\n\n        @accounts_cache[account.sis_source_id] = account\n\n        unless account.changed?\n          @success_count += 1\n          accounts_to_set_sis_batch_ids << account.id unless account.sis_batch_id == @batch.try(:id)\n          return\n        end\n\n        account.sis_batch_id = @batch.id\n\n        update_account_associations = account.root_account_id_changed? || account.parent_account_id_changed?\n        if account.save\n          data = SisBatchRollBackData.build_data(sis_batch: @batch, context: account)","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/account_importer.rb#L73-L109","documentation":"Similar to the sub-accounts guard: deleting an account via SIS is blocked with ImportError when account.courses.active.exists? — the account still contains active courses. Courses must be deleted/concluded before their account can be deleted.","triggerScenarios":"add_account with status 'deleted' for an account that has at least one active course under it.","commonSituations":"Retiring an academic department account whose courses are still unpublished/active; SIS sync not including course deletions for that subtree.","solutions":["Delete or conclude all active courses in the account (via SIS courses.csv rows with status 'deleted' or the UI) before deleting the account.","Move active courses to a different account, then delete.","Verify with a console check: account.courses.active.exists?"],"exampleFix":"// before\n# course still active\nadd_account('dept1', 'root', 'deleted', 'Department', nil)\n// after\n# courses.csv: mark course deleted first, then\nadd_account('dept1', 'root', 'deleted', 'Department', nil)","handlingStrategy":"try-catch","validationCode":"acct = root_account.all_accounts.find_by(sis_source_id: account_id)\nraise \"delete/complete courses first\" if acct&.courses&.active&.exists?","typeGuard":null,"tryCatchPattern":"begin\n  importer.add_account(id, parent_id, 'deleted', name, integration_id)\nrescue SIS::BaseImporter::ImportError => e\n  logger.warn(\"blocked: #{e.message}\")\nend","preventionTips":["Import course deletions for the subtree before account deletion","Report blocked deletions to SIS admins instead of failing the whole batch","Schedule account retirement after course clean-up"],"tags":["sis","delete","courses"],"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"}