instructure/canvas-lms · error · OSFetchError

Error retrieving results from Outcomes Service: #

Error message

Error retrieving results from Outcomes Service: #{response.body}

What it means

get_request_page checks that the Outcomes Service responded with a 2xx status code (/^2/ match on response.code). Any non-2xx (4xx auth failure, 404, 5xx server error) is raised as OSFetchError containing the response body, since authoritative outcome results could not be retrieved.

Solutions

  1. Read the response body in the error — it usually contains the service's error reason
  2. Verify JWT generation/signing and that shared secrets match between Canvas and the outcomes service
  3. Confirm the outcomes service URL configuration for the environment
  4. Check outcomes service logs for the corresponding 4xx/5xx and fix server-side or correct the request params

Example fix

// before
else
  raise OSFetchError, "Error retrieving results from Outcomes Service: #{response.body}"
// after
else
  Canvas::Errors.capture(OSFetchError.new("status=#{response.code} body=#{response.body[0, 500]}"))
  raise OSFetchError, "Error retrieving results from Outcomes Service (status #{response.code}): #{response.body}"
Defensive patterns

Strategy: try-catch

Validate before calling

raise OSFetchError, 'non-2xx' unless response.code.to_s.start_with?('2')

Try / catch

begin
  page = get_request_page(context, params)
rescue OSFetchError => e
  Canvas::Errors.capture(e)
  render json: { error: 'outcomes service unavailable' }, status: :bad_gateway
end

Prevention

When it happens

Trigger: Outcomes Service returns 401/403 (bad or expired JWT), 404 (wrong URL or context id), or 500 (server-side error) during a get_request/get_request_page call.

Common situations: Expired or mis-signed services JWT; wrong outcomes service URL per-environment; the context (course/account) not existing in the outcomes service; outcomes service internal error or maintenance.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

Thrown at app/helpers/canvas_outcomes_helper.rb:135

          results.each do |result|
            next if result[:attempts].nil?

            result[:attempts].each do |attempt|
              # Initially metadata was a string, now it's a jsonb data type. When it was a string, canvas needed
              # to parse the result returned from outcome service
              next unless attempt[:metadata].is_a? String

              attempt[:metadata] = JSON.parse(attempt[:metadata]) unless attempt[:metadata].nil?
              attempt[:metadata] = attempt[:metadata].deep_symbolize_keys unless attempt[:metadata].nil?
            end
          end
        end
        { results:, total_pages: }
      rescue
        raise OSFetchError, "Error parsing JSON results from Outcomes Service: #{response.body}"
      end
    else
      raise OSFetchError, "Error retrieving results from Outcomes Service: #{response.body}"
    end
  end

  def outcome_has_alignments?(outcome, context)
    response = get_outcome_alignments(context, outcome.id, { includes: "alignments" })
    return false if response.nil?

    response.first[:alignments].count > 0
  end

  def outcome_has_authoritative_results?(outcome, context)
    assignments = Assignment.active.where(context:).quiz_lti

    return false if assignments.blank?

    assignment_ids = assignments.pluck(:id).join(",")
    assignment_type = "canvas.assignment.quizzes"
    params = {

View on GitHub (pinned to 1c9f0bb801)