instructure/canvas-lms · error · ArgumentError
Item # has invalid final_label: # . Expected one of: #
Error message
Item #{index} has invalid final_label: #{item["final_label"]}. Expected one of: #{valid_labels.join(", ")} What it means
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.
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.
Example fix
// before raise ArgumentError unless valid_labels.include?(item["final_label"]) // after normalized = item["final_label"].to_s.strip.downcase raise ArgumentError unless valid_labels.include?(normalized)
Defensive patterns
Strategy: validation
Validate before calling
VALID_LABELS = %w[relevant needs_review irrelevant]
items.each_with_index do |item, i|
raise "item #{i}: bad final_label" unless VALID_LABELS.include?(item["final_label"].to_s)
end Try / catch
begin insight.validate_llm_response(response) rescue ArgumentError => e retry_generation_with_stricter_prompt(e.message) end
Prevention
- 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
When it happens
Trigger: 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).
Common situations: LLM outputs 'Relevant' (capitalized), 'not_relevant', or free-text labels; prompt changes weaken the output contract.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- " " must be either " " or
- Flashcard item malformed
- Improper status "# " for account # , skipping
- invalid context type
- Invalid context type
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/a7c348da2326e31d.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/discussion_topic_insight.rb:194
response_ids = response.pluck("id")
expected_sequence = (0...response.length).to_a.map(&:to_s)
if response_ids != expected_sequence
raise ArgumentError, "Response ids [#{response_ids.join(", ")}] are not sequential numbers starting from 0"
end
required_fields = %w[final_label feedback]
response.each_with_index do |item, index|
missing_fields = required_fields.select { |field| item[field].nil? }
unless missing_fields.empty?
raise ArgumentError, "Item #{index} in LLM response is missing required fields: #{missing_fields.join(", ")}"
end
valid_labels = %w[relevant needs_review irrelevant]
unless valid_labels.include?(item["final_label"])
raise ArgumentError, "Item #{index} has invalid final_label: #{item["final_label"]}. Expected one of: #{valid_labels.join(", ")}"
end
end
end
def locale
discussion_topic.course.locale || I18n.default_locale.to_s
end
def unprocessed_entries(should_preload: false)
student_user_ids = discussion_topic.course.enrollments.active
.where(enrollments: { type: "StudentEnrollment" })
.pluck(:user_id).to_set
entries = discussion_topic.root_discussion_entries.where(user_id: student_user_ids)
if should_preload
entries = entries.preload(:discussion_entry_versions, :user, :attachment)
end
entries = entries.to_aView on GitHub (pinned to 1c9f0bb801)