instructure/canvas-lms · error

invalid value, must be integer: #

Error message

invalid value, must be integer: #{value}

What it means

OutcomesAcademicBenchmarkImportApiController#parse_int converts supplied values with Kernel#Integer and raises if the value is not an integer. It backs valid_options, parse_calculation_int, and parse_rating, so any numeric outcome attribute (mastery_points, points_possible, calculation_int, rating points) must be integer-typed.

Solutions

  1. Send integers (or integer strings) for mastery_points, points_possible, calculation_int, and rating points.
  2. Omit the key entirely instead of sending an empty string when the value is not set.
  3. Round decimals client-side before submission.
  4. Validate with a numeric integer regex (^-?\d+$) before calling the API.

Example fix

// before
{ mastery_points: "3.5" }
// after
{ mastery_points: 3 }
Defensive patterns

Strategy: validation

Validate before calling

def ensure_int(value)
  Integer(value)
rescue TypeError, ArgumentError
  raise ArgumentError, "must be integer: #{value}"
end

Type guard

def int_like?(v) = /^-?\d+$/.match?(v.to_s.strip)

Try / catch

begin
  import_outcomes(options)
rescue RuntimeError => e
  raise InvalidOutcomeOption, e.message if e.message.start_with?('invalid value, must be integer:')
  raise
end

Prevention

When it happens

Trigger: Passing mastery_points/points_possible/calculation_int/rating points as a non-integer string like '0.5', 'high', '' or nil-adjacent values through the import API's valid_options hash.

Common situations: Clients sending decimal points (e.g. 1.5 points possible) for outcomes; JSON bodies with string numbers containing units or commas; forms submitting empty strings instead of omitting the field.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at app/controllers/outcomes_academic_benchmark_import_api_controller.rb:99

    end
  end

  ##
  # valid guids can only contain hex digits (letters all upper case),
  # and must be separated between a '-' [8-4-4-4-12]
  #
  #   example:  A833C528-901A-11DF-A622-0C319DFF4B22
  ##
  def valid_guid(guid)
    unless /[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}/i.match?(guid)
      raise "GUID is invalid: #{guid}"
    end
  end

  def parse_int(value)
    Integer value
  rescue
    raise "invalid value, must be integer: #{value}"
  end

  def valid_options(hash)
    options = {}
    if hash.key? :calculation_method
      options[:calculation_method] = parse_calculation_method hash[:calculation_method]
      options[:calculation_int] = parse_calculation_int options[:calculation_method], hash[:calculation_int]
    end
    options[:mastery_points] = parse_int hash[:mastery_points] if hash.key? :mastery_points
    options[:points_possible] = parse_int hash[:points_possible] if hash.key? :points_possible
    unless hash[:ratings].nil?
      raise "ratings expected to be an array" unless hash[:ratings].is_a?(Array)

      options[:ratings] = hash[:ratings].map { |r| parse_rating(r) }
    end
    options
  end

View on GitHub (pinned to 1c9f0bb801)