{"record":{"id":"b88a9413ccbc9a7e","repo":"instructure/canvas-lms","slug":"cannot-delete-the-sub-account-with-id-account-id-because-it","errorCode":null,"errorMessage":"Cannot delete the sub_account with ID: #{account_id} because it has active sub accounts.","messagePattern":"Cannot delete the sub_account with ID: #(.+?) because it has active sub accounts\\.","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/account_importer.rb","lineNumber":90,"sourceCode":"        account ||= @root_account.sub_accounts.new\n\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","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/account_importer.rb#L72-L108","documentation":"When an account import requests status 'deleted', the importer checks account.sub_accounts.active.exists? and refuses to delete an account that still has active child accounts, raising ImportError. Canvas requires bottom-up deletion of the account hierarchy.","triggerScenarios":"add_account with status 'deleted' for an account that has at least one active (non-deleted workflow_state) sub-account in the database.","commonSituations":"Deleting a whole branch of the account tree from SIS without ordering leaves first; partial imports where children were not deleted in the same or prior run.","solutions":["Include 'deleted' rows for all active child accounts in the same SIS batch, ordered before the parent.","Manually delete or deactivate the child accounts in Canvas first.","Re-check the account tree in the Canvas UI for remaining active sub-accounts."],"exampleFix":"// before\n# accounts.csv: delete parent while child stays active\nadd_account('parent1', nil, 'deleted', 'Parent', nil)\n// after\nadd_account('child1', 'parent1', 'deleted', 'Child', nil)\nadd_account('parent1', nil, 'deleted', 'Parent', nil)","handlingStrategy":"try-catch","validationCode":"if status.to_s =~ /deleted/i\n  acct = root_account.all_accounts.find_by(sis_source_id: account_id)\n  raise \"delete children first\" if acct&.sub_accounts&.active&.exists?\nend","typeGuard":null,"tryCatchPattern":"begin\n  importer.add_account(id, parent_id, 'deleted', name, integration_id)\nrescue SIS::BaseImporter::ImportError => e\n  logger.warn(\"deferring delete: #{e.message}\")\n  retry_later\nend","preventionTips":["Emit deletion rows depth-first (leaves before parents)","Do a dry-run pass computing which deletions are blocked","Reconcile account tree state before batch runs"],"tags":["sis","delete","hierarchy"],"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"}