{"record":{"id":"f592b25fdbc62d6b","repo":"instructure/canvas-lms","slug":"is-tags-differentiation-tag-group-group-id-didn-t-exist-for","errorCode":null,"errorMessage":"#{is_tags ? \"Differentiation tag\" : \"Group\"} #{group_id} didn't exist for #{is_tags ? \"differentiation tag\" : \"group\"} user","messagePattern":"#(.+?) #(.+?) didn't exist for #(.+?) user","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/sis/group_membership_importer.rb","lineNumber":60,"sourceCode":"\n      def add_group_membership(user_id, group_id, status, is_tags: false)\n        user_id = user_id.to_s\n        group_id = group_id.to_s\n        raise ImportError, \"No #{is_tags ? \"tag_id\" : \"group_id\"} given for a #{is_tags ? \"differentiation tag\" : \"group\"} user\" if group_id.blank?\n        raise ImportError, \"No user_id given for a #{is_tags ? \"differentiation tag\" : \"group\"} user\" if user_id.blank?\n        raise ImportError, \"Improper status \\\"#{status}\\\" for a #{is_tags ? \"differentiation tag\" : \"group\"} user\" unless /\\A(accepted|deleted)/i.match?(status)\n        return if @batch.skip_deletes? && status =~ /deleted/i\n\n        pseudo = @root_account.pseudonyms.find_by(sis_user_id: user_id)\n        user = pseudo&.user\n\n        group = @groups_cache[group_id]\n        scope = is_tags ? @root_account.all_differentiation_tags : @root_account.all_groups\n        group ||= scope.where(sis_source_id: group_id).preload(:context).take\n        @groups_cache[group.sis_source_id] = group if group\n\n        raise ImportError, \"User #{user_id} didn't exist for #{is_tags ? \"differentiation tag\" : \"group\"} user\" unless user\n        raise ImportError, \"#{is_tags ? \"Differentiation tag\" : \"Group\"} #{group_id} didn't exist for #{is_tags ? \"differentiation tag\" : \"group\"} user\" unless group\n\n        if group.context.is_a?(Course) && !group.context.all_real_users.where(id: user.id).exists?\n          raise ImportError, \"User #{user_id} doesn't have an enrollment in the course of #{is_tags ? \"differentiation tag\" : \"group\"} #{group_id}.\"\n        end\n\n        if group && is_tags\n          raise ImportError, \"Differentiation Tags are not enabled for Account #{group.context.account.id}.\" unless group.context.account.allow_assign_to_differentiation_tags?\n        end\n\n        # can't query group.group_memberships, since that excludes deleted memberships\n        group_membership = GroupMembership.where(group_id: group, user_id: user)\n                                          .order(Arel.sql(\"CASE WHEN workflow_state = 'accepted' THEN 0 ELSE 1 END\")).take\n        group_membership ||= group.group_memberships.build(user:)\n\n        group_membership.sis_batch_id = @batch.id\n\n        case status\n        when /accepted/i","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/sis/group_membership_importer.rb#L42-L78","documentation":"The importer looks up the group (or differentiation tag) by sis_source_id among the root account's groups/tags, including the in-memory groups_cache. If no group with that id exists, ImportError is raised because there is nothing to add the membership to.","triggerScenarios":"group_id / tag_id in the membership row does not match any existing group's sis_source_id under the root account; groups.csv not processed before memberships; group was deleted; id belongs to another root account or course not in scope.","commonSituations":"Out-of-order CSV processing (memberships before groups); typo in group id; group created in a subaccount not covered by all_groups scope; using tag ids against the non-tag path (is_tags mismatch).","solutions":["Import groups.csv (or the tag definitions) before the membership rows","Fix the group_id/tag_id so it matches the group's sis_source_id","Verify the group exists under the same root account and was not deleted","Ensure is_tags matches the id kind — tag ids must go through is_tags: true"],"exampleFix":"# before\nmembership references g_999 which was never in groups.csv\n# after\nadd \"g_999\" row to groups.csv, import it, then memberships","handlingStrategy":"validation","validationCode":"group = is_tags ? root_account.all_differentiation_tags.find_by(sis_source_id: gid)\n               : root_account.all_groups.find_by(sis_source_id: gid)\nraise \"group #{gid} not found\" unless group","typeGuard":null,"tryCatchPattern":"begin\n  importer.add_group_membership(uid, gid, status, is_tags: true)\nrescue SIS::GroupImporter::ImportError => e\n  raise unless e.message =~ /(Differentiation tag|Group) .* didn't exist/\n  Rails.logger.warn(\"Unknown group #{gid}; skipping row\")\nend","preventionTips":["Process groups.csv before group_user CSVs in the same batch","Cross-check membership group_ids against the groups file before upload","Match is_tags to the id kind; don't pass tag ids as group ids or vice versa"],"tags":["sis-import","groups","entity-not-found","ordering"],"backgroundTag":"entity-not-found","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"}