instructure/canvas-lms · error · ImportError
No institutional_tag_id given for an institutional tag
Error message
No institutional_tag_id given for an institutional tag
What it means
Raised by SisImports::InstitutionalTagImporter#add_institutional_tag when the tag_id argument is blank. The institutional tag id is the primary identifier used to match existing tags via sis_source_id, so the importer rejects any tag row lacking it before the other field validations. This is the tag-level counterpart of the 'No category_id' check.
Solutions
- Populate the institutional_tag_id column for the affected row(s) in the institutional_tags CSV and re-import.
- Fix the import mapping/scope so the tag id column is actually passed as tag_id.
- If the row is not meant to be imported, remove it from the file rather than leaving the id blank.
- Check upstream export tooling so every tag emits a unique, non-empty id.
Example fix
// before
add_institutional_tag('', 'cat-1', 'Spring Tag', 'desc', 'active')
// after
add_institutional_tag('tag-101', 'cat-1', 'Spring Tag', 'desc', 'active') Defensive patterns
Strategy: validation
Validate before calling
raise ArgumentError, 'tag_id is required' if tag_id.blank? add_institutional_tag(tag_id, category_id, name, description, status)
Try / catch
begin
importer.add_institutional_tag(tag_id, category_id, name, description, status)
rescue SisImports::ImportError => e
Rails.logger.warn("Skipping tag #{tag_id}: #{e.message}")
end Prevention
- Ensure every row in institutional_tags.csv has a non-empty institutional_tag_id.
- Drop or fix rows without identifiers before import instead of shipping blanks.
- Validate column order/mapping so tag_id is bound to the correct field.
- Make upstream exporters guarantee a unique id per tag.
When it happens
Trigger: Calling add_institutional_tag(tag_id, category_id, name, description, status) with tag_id nil, '' or whitespace; a CSV row in the institutional_tags SIS file with an empty tag id column; a column mapping/scope bug that binds an empty field to tag_id.
Common situations: Hand-built or partially regenerated SIS exports where the tag id column is missing; upstream data lacking identifiers for newly added tags; template reordering so the wrong (empty) column feeds tag_id.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- No name given for institutional tag category #
- No status given for institutional tag category #
- An institutional tag category did not pass validation
- Improper status "# " for institutional tag category #
- A course did not pass validation
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/9b00a54adeaabb20.
Report an issue: GitHub.
Appendix: source
Thrown at lib/sis/institutional_tag_importer.rb:43
yield importer
SisBatchRollBackData.bulk_insert_roll_back_data(importer.roll_back_data)
importer.success_count
end
class Work
attr_accessor :success_count, :roll_back_data
def initialize(batch, root_account, logger)
@batch = batch
@root_account = root_account
@logger = logger
@success_count = 0
@roll_back_data = []
@categories_cache = {}
end
def add_institutional_tag(tag_id, category_id, name, description, status)
raise ImportError, "No institutional_tag_id given for an institutional tag" if tag_id.blank?
raise ImportError, "No category_id given for institutional tag #{tag_id}" if category_id.blank?
raise ImportError, "No name given for institutional tag #{tag_id}" if name.blank?
raise ImportError, "No description given for institutional tag #{tag_id}" if description.blank?
raise ImportError, "No status given for institutional tag #{tag_id}" if status.blank?
raise ImportError, "Improper status \"#{status}\" for institutional tag #{tag_id}" unless /\A(active|deleted)/i.match?(status)
return if @batch.skip_deletes? && /deleted/i.match?(status)
category = @categories_cache[category_id]
category ||= InstitutionalTagCategory.find_by(root_account_id: @root_account.id, sis_source_id: category_id)
raise ImportError, "Category with id \"#{category_id}\" didn't exist for institutional tag #{tag_id}" unless category
@categories_cache[category_id] = category
tag = InstitutionalTag.find_by(root_account_id: @root_account.id, sis_source_id: tag_id)
tag ||= InstitutionalTag.new(category:,
root_account: @root_account,
sis_source_id: tag_id)
View on GitHub (pinned to 1c9f0bb801)