{"record":{"id":"25910b5725af846c","repo":"instructure/canvas-lms","slug":"invalid-description-value-rating-description","errorCode":null,"errorMessage":"invalid description value: #{rating[:description]}","messagePattern":"invalid description value: #(.+?)","errorType":"validation","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/controllers/outcomes_academic_benchmark_import_api_controller.rb","lineNumber":140,"sourceCode":"\n    value\n  end\n\n  def parse_calculation_int(calc_method, value)\n    int = value.nil? ? nil : parse_int(value)\n    unless LearningOutcome.valid_calculation_int?(int, calc_method)\n      raise \"invalid calculation_int: #{value}\"\n    end\n\n    int\n  end\n\n  def parse_rating(rating)\n    if rating.nil? || !rating.is_a?(ActionController::Parameters)\n      raise \"invalid ratings value: #{rating}\"\n    end\n    if rating[:description].nil? || !rating[:description].is_a?(String)\n      raise \"invalid description value: #{rating[:description]}\"\n    end\n\n    { description: rating[:description], points: parse_int(rating[:points]) }\n  end\nend\n","sourceCodeStart":122,"sourceCodeEnd":146,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/controllers/outcomes_academic_benchmark_import_api_controller.rb#L122-L146","documentation":"OutcomesAcademicBenchmarkImportApiController#parse_rating checks that each rating has a non-nil String :description and raises otherwise. The description names the mastery level and is required for every rating in the array.","triggerScenarios":"A ratings entry missing :description, having nil description, or a non-string description (number, hash) — e.g. { points: 3 } or { description: 5, points: 3 }.","commonSituations":"Forms that send the rating label under a different key (name/label instead of description); JSON where description was dropped by a serializer; clients sending numeric level indexes instead of text.","solutions":["Include a string description on every rating object.","Map alternate keys (e.g. 'label') to description before sending.","Coerce numeric labels to strings only if that is the intent; otherwise supply real text.","Validate presence and type of description client-side."],"exampleFix":"// before\nratings: [{ points: 3 }]\n// after\nratings: [{ description: \"Mastery\", points: 3 }]","handlingStrategy":"validation","validationCode":"raise ArgumentError unless ratings.all? { |r| r[:description].is_a?(String) && !r[:description].empty? }","typeGuard":"def described_rating?(r) = r[:description].is_a?(String) && !r[:description].nil?","tryCatchPattern":"begin\n  import_outcomes(options)\nrescue RuntimeError => e\n  raise InvalidRatingDescription, e.message if e.message.start_with?('invalid description value:')\n  raise\nend","preventionTips":["Always include a non-empty string description per rating.","Map alternate label keys to description before sending.","Don't send numeric level ids as descriptions.","Validate description presence/type client-side."],"tags":["api","ratings","validation"],"backgroundTag":"empty-required-field","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"}