{"record":{"id":"2ab542198e541dfd","repo":"instructure/canvas-lms","slug":"invalid-csv-file","errorCode":null,"errorMessage":"Invalid CSV File","messagePattern":"Invalid CSV File","errorType":"validation","errorClass":"DataFormatError","httpStatus":null,"severity":"error","filePath":"lib/outcomes/csv_importer.rb","lineNumber":63,"sourceCode":"\n    BATCH_SIZE = 1000\n\n    def initialize(import, file)\n      @import = import\n      @file = file\n    end\n\n    delegate :context, to: :@import\n\n    def run(&)\n      status = { progress: 0, errors: [] }\n      yield status\n\n      file_errors = []\n      begin\n        parse_file(&)\n      rescue CSV::MalformedCSVError\n        raise DataFormatError, I18n.t(\"Invalid CSV File\")\n      rescue ParseError => e\n        raise DataFormatError, e.message\n      rescue ActiveRecord::StatementInvalid => e\n        raise DataFormatError, I18n.t(\"Database error (%{err})\", err: e.message)\n      end\n      status = {\n        errors: file_errors,\n        progress: 100\n      }\n      yield status\n    end\n\n    def parse_file\n      headers = nil\n      total = file_line_count\n      raise ParseError, I18n.t(\"File has no data\") if total < 1\n\n      separator = test_header_i18n","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/outcomes/csv_importer.rb#L45-L81","documentation":"Outcomes::CsvImporter#run parses an outcomes CSV; if CSV parsing raises CSV::MalformedCSVError (structurally broken CSV — unbalanced quotes, bad encoding artifacts, invalid row shapes), the importer wraps it as DataFormatError with the i18n message 'Invalid CSV File'. This signals the file itself is not parseable CSV rather than a data/content problem.","triggerScenarios":"Uploading/importing an outcomes CSV where CSV.parse-level parsing fails: unterminated quotes, stray characters after a quoted field, mixed encodings producing invalid bytes.","commonSituations":"Files edited in Excel and re-saved with odd quoting; files exported with a non-UTF8 encoding; truncated uploads; CSVs using multiline quoted fields that got mangled by copy/paste.","solutions":["Open the file in a CSV validator or spreadsheet app and fix malformed quoting/rows, then re-import.","Re-export the CSV as UTF-8 with standard double-quote escaping from the source system.","Check for truncated uploads (compare file size/line count to the source) and re-upload.","If generating the CSV programmatically, write it with a proper CSV library instead of string concatenation."],"exampleFix":"// before (manual CSV generation)\nout << \"#{name},#{url}\" # breaks when name contains commas/quotes\n// after\nrequire 'csv'\nout << CSV.generate_line([name, url])","handlingStrategy":"validation","validationCode":"begin\n  CSV.parse(File.read(path))\nrescue CSV::MalformedCSVError => e\n  abort \"invalid CSV: #{e.message}\"\nend","typeGuard":"def parseable_csv?(path)\n  CSV.parse(File.read(path))\n  true\nrescue CSV::MalformedCSVError, ArgumentError\n  false\nend","tryCatchPattern":"begin\n  importer.run\nrescue Outcomes::CsvImporter::DataFormatError => e\n  flash[:error] = e.message # 'Invalid CSV File'\nend","preventionTips":["Generate CSVs with a CSV library, never string concatenation.","Export as UTF-8 with standard double-quote quoting.","Pre-validate files client-side before upload."],"tags":["csv","import","outcomes","parse"],"backgroundTag":"csv-parse-error","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"}