instructure/canvas-lms · error · InvalidDataError
Points for rating tier
Error message
Points for rating tier %{index} not present What it means
Raised by Outcomes::CsvImporter#parse_ratings when a rating tier has a missing/blank points value. Ratings are read as consecutive points,description pairs; after dropping trailing nils, any pair whose points cell is nil or blank triggers this InvalidDataError naming the 1-based tier index. This guarantees every rating tier has a numeric threshold.
Solutions
- Fill in a numeric value in every ratings points cell (points and description strictly alternate).
- Fix the number of cells so pairs align: points, description, points, description...
- Regenerate the ratings section from the template, one points cell per description.
Example fix
// before ratings: 3,,Meets,5,Exemplary // after ratings: 3,Meets,5,Exemplary
Defensive patterns
Strategy: validation
Validate before calling
cells = row['ratings'].to_a.drop_while { |c| c.nil? }.reverse.drop_while(&:nil?).reverse
pairs = cells.each_slice(2).to_a
raise 'rating points missing' if pairs.any? { |pts, _| pts.nil? || pts.to_s.strip.empty? } Try / catch
begin
importer.run
rescue Outcomes::Import::InvalidDataError => e
errors << "Row #{i}: #{e.message}"
end Prevention
- Fill every rating points cell — no blanks inside the ratings section
- Keep points/description pairs strictly alternating
- Count commas: an odd number of ratings cells usually means a missing points value
When it happens
Trigger: Ratings cells like `4,,Exemplary,` — an empty points cell between descriptions; an odd number of ratings cells so slicing pairs puts a description where points should be; trailing commas creating misalignment.
Common situations: Hand-built CSV where someone left the points cell empty assuming a default; extra/missing commas shifting the pair alignment; templates where users filled descriptions but not points.
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
- Friendly description is too long (maximum is 255 characters)
- Invalid fields after ratings
- Invalid fields
- Invalid value for
- Missing 'Rubric Name' in some rows.
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/fc53d12d4fd2a15a.
Report an issue: GitHub.
Appendix: source
Thrown at lib/outcomes/csv_importer.rb:174
ratings = row[headers.length..]
object = simple.to_h
object[:ratings] = parse_ratings(ratings)
object[:learning_outcome_group_id] = @import[:learning_outcome_group_id]
if object[:mastery_points].present?
object[:mastery_points] = strict_parse_float(object[:mastery_points], I18n.t("mastery points"))
end
if object[:friendly_description].present? && object[:friendly_description].length > 255
raise InvalidDataError, I18n.t("Friendly description is too long (maximum is 255 characters)")
end
import_object(object)
end
def parse_ratings(ratings)
prior = nil
drop_trailing_nils(ratings).each_slice(2).to_a.map.with_index(1) do |(points, description), index|
raise InvalidDataError, I18n.t("Points for rating tier %{index} not present", index:) if points.nil? || points.blank?
points = strict_parse_float(points, I18n.t("rating tier %{index} threshold", index:))
if prior.present? && prior < points
raise InvalidDataError, I18n.t(
"Points for tier %{index} must be less than points for prior tier (%{points} is greater than %{prior})",
index:,
prior:,
points:
)
end
prior = points
{ points:, description: }
end
end
def normalize_i18n(string)View on GitHub (pinned to 1c9f0bb801)