{"record":{"id":"86ae047823caed73","repo":"instructure/canvas-lms","slug":"summary-response-missing","errorCode":null,"errorMessage":"Summary response missing","messagePattern":"Summary response missing","errorType":"exception","errorClass":"CedarUnavailable","httpStatus":null,"severity":"error","filePath":"app/services/study_assist.rb","lineNumber":283,"sourceCode":"    def summarize_kind(content)\n      case content.kind\n      when :page then \"page\"\n      when :file then \"file\"\n      else \"material\"\n      end\n    end\n\n    def build_response(tool_key, raw)\n      case tool_key\n      when :summarize then build_summarize_response(raw)\n      when :quiz then build_quiz_response(raw)\n      when :flashcards then build_flashcards_response(raw)\n      end\n    end\n\n    def build_summarize_response(raw)\n      text = raw.to_s.strip\n      raise CedarUnavailable, \"Summary response missing\" if text.blank?\n\n      { response: text }\n    end\n\n    def build_quiz_response(raw)\n      items = parse_json_array!(raw)\n      raise CedarUnavailable, \"Quiz response missing items\" if items.blank? || !items.is_a?(Array)\n\n      quiz_items = items.first(10).map do |item|\n        question = item[:question] || item[\"question\"]\n        options = item[:options] || item[\"options\"]\n        result = item[:result] || item[\"result\"]\n        raise CedarUnavailable, \"Quiz item malformed\" if question.blank? || options.blank? || result.nil?\n\n        { question:, answers: options, correctAnswerIndex: result.to_i }\n      end\n\n      { quizItems: quiz_items }","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/study_assist.rb#L265-L301","documentation":"Guard in StudyAssist#build_summarize_response: the LLM/Cedar tool returned an empty or blank summary string for the summarize request, so CedarUnavailable is raised to signal the AI backend produced no usable content.","triggerScenarios":"build_response -> build_summarize_response when raw (the Cedar completion for the :summarize tool) is nil, empty, or whitespace-only.","commonSituations":"Cedar silently returning an empty completion (e.g. content too short to summarize, prompt substitution issue for the KIND placeholder, or the model returning a refusal-only/empty body).","solutions":["Re-run the summarize request — an empty completion is often transient.","Check the input content: extremely short or empty source text may produce nothing; ensure resolve_content returned real text.","Inspect prompt_for_cedar substitution for :summarize (KIND) to confirm the prompt is well-formed.","Check Cedar-side logs for completion truncation or content filtering of the response."],"exampleFix":"// before\n# no check on content before summarizing\nsummary = service.call(tool: :summarize)\n\n// after\nraise StudyAssist::ContentUnavailable, 'Nothing to summarize' if content.text.blank?\nsummary = service.call(tool: :summarize)","handlingStrategy":"retry","validationCode":"raise ArgumentError, 'nothing to summarize' if content.text.strip.blank?","typeGuard":null,"tryCatchPattern":"begin\n  summary = service.call(tool: :summarize)\nrescue StudyAssist::CedarUnavailable\n  summary = retry_with_backoff(tries: 2) { service.call(tool: :summarize) }\nend","preventionTips":["Ensure source content has non-trivial text before summarizing","Verify prompt_for_cedar KIND substitution produces a valid prompt","Retry once on blank completions before surfacing the error"],"tags":["llm","empty-response","summarize"],"backgroundTag":"empty-response-body","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"}