instructure/canvas-lms · error · CedarUnavailable

Invalid JSON response from Cedar

Error message

Invalid JSON response from Cedar

What it means

parse_json_array! runs the raw Cedar completion through InstLLMHelper.extract_json_array and raises CedarUnavailable 'Invalid JSON response from Cedar' when extraction returns nil — i.e. no JSON array could be recovered from the model's text at all.

Solutions

  1. Retry the request — LLM JSON formatting failures are frequently transient.
  2. Log the raw completion and test it against InstLLMHelper.extract_json_array to see why extraction fails.
  3. Adjust the prompt to demand strict JSON-array output with no prose or markdown fences.
  4. If the model's fences are the issue, verify the extract_json_array helper version supports them, or strip code fences before parsing.

Example fix

// before
# raw model text goes straight in
items = parse_json_array!(raw)

// after
stripped = raw.to_s.gsub(/```(json)?|```/, '').strip
items = InstLLMHelper.extract_json_array(stripped)
raise StudyAssist::CedarUnavailable, 'Invalid JSON response from Cedar' if items.nil?
Defensive patterns

Strategy: try-catch

Validate before calling

def recoverable_json?(raw)
  !InstLLMHelper.extract_json_array(raw.to_s).nil?
end

Type guard

def extractable_array?(raw)
  InstLLMHelper.extract_json_array(raw.to_s).is_a?(Array)
end

Try / catch

begin
  parsed = parse_json_array!(raw)
rescue StudyAssist::CedarUnavailable
  stripped = raw.to_s.gsub(/```(json)?|```/, '').strip
  parsed = InstLLMHelper.extract_json_array(stripped)
  raise if parsed.nil?
end

Prevention

When it happens

Trigger: build_quiz_response or build_flashcards_response -> parse_json_array! where the raw completion contains no parseable JSON array (prose answer, fenced garbage, truncated JSON, or empty string).

Common situations: Model responding conversationally ('Here are your quiz questions: ...') with malformed or missing JSON; token-limit truncation cutting the array before the closing bracket; a Cedar/model change altering output format away from what extract_json_array expects.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


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

Appendix: source

Thrown at app/services/study_assist.rb:321

    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
  end
end

View on GitHub (pinned to 1c9f0bb801)