instructure/canvas-lms · error · ParseError

Missing required fields

Error message

Missing required fields: %{fields}

What it means

Raised by Outcomes::CsvImporter#validate_headers when one or more of the REQUIRED_FIELDS (vendor_guid, title, etc.) are absent from the header row before the 'ratings' column. The importer computes the set difference REQUIRED_FIELDS - headers and fails with a ParseError listing the missing fields. It guarantees every imported outcome row has the mandatory columns available.

Solutions

  1. Add the missing columns named in the error message (e.g. vendor_guid) to the header row before 'ratings'.
  2. Start from the official import template to guarantee the required header set.
  3. Check exact spelling/casing of headers — they must match REQUIRED_FIELDS exactly, e.g. 'vendor_guid', 'title'.

Example fix

// before
title,description,ratings
// after
vendor_guid,title,description,ratings
Defensive patterns

Strategy: validation

Validate before calling

REQUIRED = %w[vendor_guid title description ratings]
headers = CSV.open(path, &:first).compact
missing = REQUIRED - headers
raise "missing columns: #{missing.join(', ')}" unless missing.empty?

Try / catch

begin
  importer.parse_file
rescue Outcomes::CsvImporter::ParseError => e
  show_template_error(e.message) # e.g. 'Missing required fields: ["vendor_guid"]'
end

Prevention

When it happens

Trigger: A header row like `title,description,ratings` omitting `vendor_guid`; renamed headers (e.g. 'Title' with different casing is not matched, since matching is exact on the downcased symbol); truncated or reordered template where a required column was deleted.

Common situations: Using a hand-built CSV that forgot the vendor_guid column; editing the template and accidentally deleting a required column; exporting from a system whose column names differ from Canvas's expected ones.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at lib/outcomes/csv_importer.rb:146

    def check_encoding(str)
      encoded = str&.force_encoding("utf-8")
      valid = (encoded || "").valid_encoding?
      raise ParseError, I18n.t("Not a valid utf-8 string: %{string}", string: str.inspect) unless valid

      encoded
    end

    def validate_headers(row, _index)
      main_columns_end = row.find_index("ratings") || row.length
      headers = row.slice(0, main_columns_end).map(&:to_sym)

      after_ratings = row[(main_columns_end + 1)..] || []
      after_ratings = after_ratings.compact_blank.map(&:to_s)
      raise ParseError, I18n.t("Invalid fields after ratings: %{fields}", fields: after_ratings.inspect) unless after_ratings.empty?

      missing = (REQUIRED_FIELDS - headers).map(&:to_s)
      raise ParseError, I18n.t("Missing required fields: %{fields}", fields: missing.inspect) unless missing.empty?

      invalid = (headers - OPTIONAL_FIELDS - REQUIRED_FIELDS).map(&:to_s)
      raise ParseError, I18n.t("Invalid fields: %{fields}", fields: invalid.inspect) unless invalid.empty?

      headers
    end

    def import_row(headers, row)
      simple = headers.zip(row).to_h
      ratings = row[headers.length..]

      object = simple.to_h
      object[:ratings] = parse_ratings(ratings)
      object[:learning_outcome_group_id] = @import[:learning_outcome_group_id]
      if object[:mastery_points].present?
        object[:mastery_points] = strict_parse_float(object[:mastery_points], I18n.t("mastery points"))
      end
      if object[:friendly_description].present? && object[:friendly_description].length > 255

View on GitHub (pinned to 1c9f0bb801)