{"record":{"id":"e352543b228f57c4","repo":"instructure/canvas-lms","slug":"missing-required-fields-fields","errorCode":null,"errorMessage":"Missing required fields: %{fields}","messagePattern":"Missing required fields: %(.+?)","errorType":"validation","errorClass":"ParseError","httpStatus":null,"severity":"error","filePath":"lib/outcomes/csv_importer.rb","lineNumber":146,"sourceCode":"\n    def check_encoding(str)\n      encoded = str&.force_encoding(\"utf-8\")\n      valid = (encoded || \"\").valid_encoding?\n      raise ParseError, I18n.t(\"Not a valid utf-8 string: %{string}\", string: str.inspect) unless valid\n\n      encoded\n    end\n\n    def validate_headers(row, _index)\n      main_columns_end = row.find_index(\"ratings\") || row.length\n      headers = row.slice(0, main_columns_end).map(&:to_sym)\n\n      after_ratings = row[(main_columns_end + 1)..] || []\n      after_ratings = after_ratings.compact_blank.map(&:to_s)\n      raise ParseError, I18n.t(\"Invalid fields after ratings: %{fields}\", fields: after_ratings.inspect) unless after_ratings.empty?\n\n      missing = (REQUIRED_FIELDS - headers).map(&:to_s)\n      raise ParseError, I18n.t(\"Missing required fields: %{fields}\", fields: missing.inspect) unless missing.empty?\n\n      invalid = (headers - OPTIONAL_FIELDS - REQUIRED_FIELDS).map(&:to_s)\n      raise ParseError, I18n.t(\"Invalid fields: %{fields}\", fields: invalid.inspect) unless invalid.empty?\n\n      headers\n    end\n\n    def import_row(headers, row)\n      simple = headers.zip(row).to_h\n      ratings = row[headers.length..]\n\n      object = simple.to_h\n      object[:ratings] = parse_ratings(ratings)\n      object[:learning_outcome_group_id] = @import[:learning_outcome_group_id]\n      if object[:mastery_points].present?\n        object[:mastery_points] = strict_parse_float(object[:mastery_points], I18n.t(\"mastery points\"))\n      end\n      if object[:friendly_description].present? && object[:friendly_description].length > 255","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/outcomes/csv_importer.rb#L128-L164","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add the missing columns named in the error message (e.g. vendor_guid) to the header row before 'ratings'.","Start from the official import template to guarantee the required header set.","Check exact spelling/casing of headers — they must match REQUIRED_FIELDS exactly, e.g. 'vendor_guid', 'title'."],"exampleFix":"// before\ntitle,description,ratings\n// after\nvendor_guid,title,description,ratings","handlingStrategy":"validation","validationCode":"REQUIRED = %w[vendor_guid title description ratings]\nheaders = CSV.open(path, &:first).compact\nmissing = REQUIRED - headers\nraise \"missing columns: #{missing.join(', ')}\" unless missing.empty?","typeGuard":null,"tryCatchPattern":"begin\n  importer.parse_file\nrescue Outcomes::CsvImporter::ParseError => e\n  show_template_error(e.message) # e.g. 'Missing required fields: [\"vendor_guid\"]'\nend","preventionTips":["Start every import from the official template","Check exact header spelling and casing","Script a header check (REQUIRED_FIELDS - headers) before importing"],"tags":["csv","headers","missing-field","import"],"backgroundTag":"missing-required-argument","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"}