instructure/canvas-lms · error · CedarUnavailable

Flashcards response missing items

Error message

Flashcards response missing items

What it means

Guard in StudyAssist#build_flashcards_response: the Cedar/LLM flashcards response parsed to an empty value or a non-array, so CedarUnavailable is raised — the AI backend returned no usable flashcard items.

Solutions

  1. Retry the flashcards generation — empty output is often transient.
  2. Supply longer, more fact-dense source content.
  3. Log raw Cedar output and verify extract_json_array can recover the array (check for truncation).
  4. Tighten the flashcards prompt to require a non-empty JSON array of {question, answer}.

Example fix

// before
# assume cards always come back

// after
cards = service.call(tool: :flashcards) rescue nil
retry_once if cards.nil? # transient empty LLM output
Defensive patterns

Strategy: retry

Type guard

def usable_card_array?(raw)
  parsed = InstLLMHelper.extract_json_array(raw.to_s)
  parsed.is_a?(Array) && parsed.any?
end

Try / catch

begin
  cards = service.call(tool: :flashcards)
rescue StudyAssist::CedarUnavailable
  cards = service.call(tool: :flashcards) # retry transient empty output
end

Prevention

When it happens

Trigger: build_response -> build_flashcards_response where parse_json_array! produced an empty array or a non-array value for the :flashcards tool.

Common situations: Short or non-prose source content (e.g. a single formula) giving the model nothing to cardify; the LLM answering in prose instead of JSON; output truncated by token limits so the array never materializes.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/80ce56adb8557583. Report an issue: GitHub.

Appendix: source

Thrown at app/services/study_assist.rb:306

    def build_quiz_response(raw)
      items = parse_json_array!(raw)
      raise CedarUnavailable, "Quiz response missing items" if items.blank? || !items.is_a?(Array)

      quiz_items = items.first(10).map do |item|
        question = item[:question] || item["question"]
        options = item[:options] || item["options"]
        result = item[:result] || item["result"]
        raise CedarUnavailable, "Quiz item malformed" if question.blank? || options.blank? || result.nil?

        { question:, answers: options, correctAnswerIndex: result.to_i }
      end

      { quizItems: quiz_items }
    end

    def build_flashcards_response(raw)
      cards = parse_json_array!(raw)
      raise CedarUnavailable, "Flashcards response missing items" if cards.blank? || !cards.is_a?(Array)

      flash_cards = cards.first(10).map do |card|
        question = card[:question] || card["question"]
        answer = card[:answer] || card["answer"]
        raise CedarUnavailable, "Flashcard item malformed" if question.blank? || answer.blank?

        { question:, answer: }
      end

      { flashCards: flash_cards }
    end

    def parse_json_array!(raw)
      parsed = InstLLMHelper.extract_json_array(raw.to_s)
      raise CedarUnavailable, "Invalid JSON response from Cedar" if parsed.nil?

      parsed
    end

View on GitHub (pinned to 1c9f0bb801)