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
- Retry the request — LLM JSON formatting failures are frequently transient.
- Log the raw completion and test it against InstLLMHelper.extract_json_array to see why extraction fails.
- Adjust the prompt to demand strict JSON-array output with no prose or markdown fences.
- 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
- Prompt the model for strict JSON arrays with no surrounding prose or code fences
- Test raw completions against extract_json_array during prompt/model changes
- Strip markdown fences before parsing as a standard pre-step
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Flashcards response missing items
- Quiz response missing items
- Error parsing JSON results from Outcomes Service: #
- Flashcard item malformed
- Quiz item malformed
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)