{"record":{"id":"a7c348da2326e31d","repo":"instructure/canvas-lms","slug":"item-index-has-invalid-final-label-item-final-label-expected","errorCode":null,"errorMessage":"Item #{index} has invalid final_label: #{item[\"final_label\"]}. Expected one of: #{valid_labels.join(\", \")}","messagePattern":"Item #(.+?) has invalid final_label: #(.+?)\\. Expected one of: #(.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"app/models/discussion_topic_insight.rb","lineNumber":194,"sourceCode":"    response_ids = response.pluck(\"id\")\n    expected_sequence = (0...response.length).to_a.map(&:to_s)\n\n    if response_ids != expected_sequence\n      raise ArgumentError, \"Response ids [#{response_ids.join(\", \")}] are not sequential numbers starting from 0\"\n    end\n\n    required_fields = %w[final_label feedback]\n\n    response.each_with_index do |item, index|\n      missing_fields = required_fields.select { |field| item[field].nil? }\n\n      unless missing_fields.empty?\n        raise ArgumentError, \"Item #{index} in LLM response is missing required fields: #{missing_fields.join(\", \")}\"\n      end\n\n      valid_labels = %w[relevant needs_review irrelevant]\n      unless valid_labels.include?(item[\"final_label\"])\n        raise ArgumentError, \"Item #{index} has invalid final_label: #{item[\"final_label\"]}. Expected one of: #{valid_labels.join(\", \")}\"\n      end\n    end\n  end\n\n  def locale\n    discussion_topic.course.locale || I18n.default_locale.to_s\n  end\n\n  def unprocessed_entries(should_preload: false)\n    student_user_ids = discussion_topic.course.enrollments.active\n                                       .where(enrollments: { type: \"StudentEnrollment\" })\n                                       .pluck(:user_id).to_set\n\n    entries = discussion_topic.root_discussion_entries.where(user_id: student_user_ids)\n    if should_preload\n      entries = entries.preload(:discussion_entry_versions, :user, :attachment)\n    end\n    entries = entries.to_a","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/discussion_topic_insight.rb#L176-L212","documentation":"DiscussionTopicInsight.validate_llm_response checks each LLM-returned item against required fields and an allowed set of final_label values ('relevant', 'needs_review', 'irrelevant'). If an item's final_label is outside that set, it raises ArgumentError naming the item index, the bad value, and the valid options.","triggerScenarios":"generate() parses an LLM response whose item at some index has a final_label not in the allowed enum (typos, model hallucination, prompt/schema drift).","commonSituations":"LLM outputs 'Relevant' (capitalized), 'not_relevant', or free-text labels; prompt changes weaken the output contract.","solutions":["Tighten the LLM prompt/schema to enforce the exact enum values.","Normalize the label (downcase/trim) before validation.","Reject or retry the generation when any item has an invalid label.","Add few-shot examples showing the exact final_label values."],"exampleFix":"// before\nraise ArgumentError unless valid_labels.include?(item[\"final_label\"])\n// after\nnormalized = item[\"final_label\"].to_s.strip.downcase\nraise ArgumentError unless valid_labels.include?(normalized)","handlingStrategy":"validation","validationCode":"VALID_LABELS = %w[relevant needs_review irrelevant]\nitems.each_with_index do |item, i|\n  raise \"item #{i}: bad final_label\" unless VALID_LABELS.include?(item[\"final_label\"].to_s)\nend","typeGuard":null,"tryCatchPattern":"begin\n  insight.validate_llm_response(response)\nrescue ArgumentError => e\n  retry_generation_with_stricter_prompt(e.message)\nend","preventionTips":["Pin the exact enum strings in the LLM prompt with few-shot examples","Normalize labels (strip/downcase) before validating","Schema-constrain LLM output when supported"],"tags":["validation","llm","enum"],"backgroundTag":"invalid-enum-value","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"}