instructure/canvas-lms · error · ImportError
No tag_set_id or course_id given for differentiation tag #
Error message
No tag_set_id or course_id given for differentiation tag #{tag_id}. At least one is required for new tags. What it means
add_tag resolves the tag's context either from an explicit tag_set (tag_set_id) or from a course_id. If neither a tag_set nor a course_id was supplied and the tag referenced by tag_id cannot be found (so no context can be inferred), the importer raises because it has no context in which to create the new differentiation tag.
Solutions
- Add a course_id (or tag_set_id) to the SIS row so the tag has a context
- Correct the tag_id so it matches an existing tag whose context can be used
- If the import is API/console-driven, pass tag_set_id or course_id to add_tag
- Validate the CSV before upload: every new tag row must include at least one of tag_set_id or course_id
Example fix
# before (CSV row) "tag_123,,New Tag" # no tag_set_id, no course_id # after "tag_123,C123,New Tag" # course_id supplied
Defensive patterns
Strategy: validation
Validate before calling
raise 'tag row needs tag_set_id or course_id' if tag_set_id.blank? && course_id.blank? # or in CSV lint: require at least one of the two columns for every new tag_id
Try / catch
begin
importer.add_tag(tag_id, name, tag_set_id: tsid, course_id: cid)
rescue SIS::GroupImporter::ImportError => e
raise unless e.message =~ /No tag_set_id or course_id given/
Rails.logger.error("Tag row missing context: #{e.message}")
end Prevention
- Require course_id or tag_set_id in every new-tag CSV row via a pre-import validator
- Verify tag_ids of existing tags before relying on context inference
- Keep a single CSV template that always includes both columns
When it happens
Trigger: add_tag called with a tag_id that does not match an existing tag (so tag&.context is nil) and with neither tag_set_id nor course_id provided in the row.
Common situations: SIS CSV groups file for differentiation tags missing course_id column while using a new tag_id (creation attempt); typo in tag_id so the existing-tag lookup misses; importer invoked programmatically without context parameters.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- assessor and assessee required
- association required
- Cannot find # for ID: #
- Context is required, but none found
- context required
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/84131e93cb57ed7e.
Report an issue: GitHub.
Appendix: source
Thrown at lib/sis/group_importer.rb:228
if tag_set_id.present?
tag_set = find_category(tag_set_id, context, :differentiation_tag_category, "differentiation_tag", tag_id)
end
tag = @root_account.all_differentiation_tags.find_by(sis_source_id: tag_id)
if tag_set
context = tag_set.context
raise ImportError, "Differentiation Tags are not enabled for Account #{context.account.id}." unless context.account.allow_assign_to_differentiation_tags?
if tag
tag.group_category = tag_set
else
tag = tag_set.groups.non_collaborative.new(name:, sis_source_id: tag_id)
end
end
context ||= tag&.context
raise ImportError, "No tag_set_id or course_id given for differentiation tag #{tag_id}. At least one is required for new tags." unless context
can_change_context?(tag, context, "differentiation_tag", tag_id)
tag ||= context.groups.new(name:, non_collaborative: true, sis_source_id: tag_id)
tag.name = name if name.present? && !tag.stuck_sis_fields.include?(:name)
tag.context = context
tag.sis_batch_id = @batch.id
tag.workflow_state = (status == "deleted") ? "deleted" : "available"
# Ensure tag category context matches tag context
if tag&.group_category &&
tag.group_category.context_id != context.id &&
tag.group_category.context_type == context.class_name
tag.group_category.update!(context_id: context.id)
else
tag_set ||= context.differentiation_tag_categories.create!(name:, non_collaborative: true)
# If adding as a single tag, have the tag set match the single tag status
tag_set.destroy if status == "deleted"View on GitHub (pinned to 1c9f0bb801)