instructure/canvas-lms · error · DataFormatError
Missing 'Criteria Name' for #
Error message
Missing 'Criteria Name' for #{rubric_name} What it means
RubricImport#process_rubrics groups imported rows by rubric name and iterates criteria per rubric. Each criterion row must carry a non-blank :description (its name); otherwise a DataFormatError is raised naming the rubric. It guards against building RubricCriterion records with empty descriptions, which Canvas does not allow.
Solutions
- Open the import file and fill in the missing 'Criteria Name' for every criterion row of the named rubric, then re-import.
- Pre-validate the parsed rubric_data in the caller: reject rows with blank description before calling process_rubrics.
- If rows are stray artifacts (e.g. trailing blanks), remove those rows from the import file.
- If the file is generated programmatically, fix the generator to always emit a description per criterion.
Example fix
// before
rubric_data.each_with_index do |criterion, _i|
build_criterion(criterion) # raises at line 115 if description blank
end
// after
rubric_data.each_with_index do |criterion, i|
if criterion[:description].blank?
raise DataFormatError, "Missing 'Criteria Name' for #{rubric_name} (row #{i + 1})"
end
build_criterion(criterion)
end Defensive patterns
Strategy: validation
Validate before calling
bad = rubric_data.each_with_index.select { |c, _| c[:description].blank? }
raise ArgumentError, "blank criteria names for #{rubric_name}" unless bad.empty? Type guard
def valid_criterion?(c) c.is_a?(Hash) && c[:description].present? && c[:ratings].is_a?(Array) end
Try / catch
begin
import.process_rubrics
rescue DataFormatError => e
Rails.logger.warn("Rubric import rejected: #{e.message}")
render json: { errors: [e.message] }, status: :unprocessable_entity
end Prevention
- Validate every criterion row (description + ratings present) before calling process_rubrics.
- Trim and re-check spreadsheet cells; empty-looking cells often contain whitespace.
- Surface row numbers in your own pre-validation errors so users can fix CSVs quickly.
When it happens
Trigger: Call process_rubrics on a RubricImport whose parsed CSV/data contains a criterion row under some rubric_name where criterion[:description] is nil or empty string (e.g. a row with a rubric name but blank criteria name column).
Common situations: Importing a rubric CSV where the 'Criteria Name' (description) cell is empty for one or more rows; exporting/editing a spreadsheet and deleting the criteria column values but leaving rating columns; extra trailing rows with ratings but no criterion title.
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
- Missing ratings for #
- Improper status "# " for abstract course #
- Improper status "# " for # # , skipping
- No account_id given for an account
- No name given for account #
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/8a88f8c6ff3de1f2.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/rubric_import.rb:115
track_error
job_failed!
end
end
def process_rubrics
rubrics_by_name = RubricCSVImporter.new(attachment).parse
raise DataFormatError, I18n.t("The file is empty or does not contain valid rubric data.") if rubrics_by_name.empty?
total_rubrics = rubrics_by_name.keys.count
error_data = []
rubrics_by_name.each_with_index do |(rubric_name, rubric_data), rubric_index|
raise DataFormatError, I18n.t("Missing 'Rubric Name' in some rows.") if rubric_name.blank?
rubric = context.rubrics.build(rubric_imports_id: id)
criteria_hash = {}
rubric_data.each_with_index do |criterion, criterion_index|
raise DataFormatError, "Missing 'Criteria Name' for #{rubric_name}" if criterion[:description].blank?
raise DataFormatError, "Missing ratings for #{criterion[:description]}" if criterion[:ratings].empty?
ratings_hash = {}
criterion[:ratings].each_with_index do |rating, rating_index|
ratings_hash[rating_index.to_s] = {
"description" => rating[:description],
"long_description" => rating[:long_description],
"points" => rating[:points]
}
end
criteria_hash[criterion_index.to_s] = {
"description" => criterion[:description],
"long_description" => criterion[:long_description],
"ratings" => ratings_hash
}
if context.root_account.feature_enabled?(:rubric_criterion_range)
criteria_hash[criterion_index.to_s]["criterion_use_range"] = criterion[:criterion_use_range]
endView on GitHub (pinned to 1c9f0bb801)