instructure/canvas-lms · error · ParseError

File has no data

Error message

File has no data

What it means

Outcomes::CsvImporter#parse_file first counts the file's lines (file_line_count) and raises ParseError 'File has no data' when the count is below 1, i.e. the uploaded CSV is empty (zero content lines). The importer cannot even attempt header validation without at least one line.

Solutions

  1. Verify the file has content (non-zero size, at least one line) before importing.
  2. Re-export or re-download the outcomes CSV template and populate it with header + data rows.
  3. Add a pre-upload client-side check rejecting empty files with a clear message.
  4. If using an API/import job, confirm the attachment param points to the actual CSV, not an empty temp file.

Example fix

// before
importer = Outcomes::CsvImporter.new(file: uploaded)
importer.run
// after
raise 'CSV file is empty' unless File.size(uploaded.path) > 0
importer = Outcomes::CsvImporter.new(file: uploaded)
importer.run
Defensive patterns

Strategy: validation

Validate before calling

raise 'CSV file is empty' if file.nil? || File.size(file.path).zero?

Type guard

def non_empty_file?(file)
  file.respond_to?(:path) && File.exist?(file.path) && File.size(file.path) > 0
end

Try / catch

begin
  importer.run
rescue Outcomes::CsvImporter::ParseError => e
  flash[:error] = e.message # 'File has no data'
end

Prevention

When it happens

Trigger: Importing outcomes from a CSV attachment that is completely empty (0 bytes or only a newline stripped by the line counter), so total < 1.

Common situations: User selected the wrong/blank file; upload pipeline saved an empty attachment; template file was cleared of all content before upload; export step upstream produced an empty file.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at lib/outcomes/csv_importer.rb:79

        parse_file(&)
      rescue CSV::MalformedCSVError
        raise DataFormatError, I18n.t("Invalid CSV File")
      rescue ParseError => e
        raise DataFormatError, e.message
      rescue ActiveRecord::StatementInvalid => e
        raise DataFormatError, I18n.t("Database error (%{err})", err: e.message)
      end
      status = {
        errors: file_errors,
        progress: 100
      }
      yield status
    end

    def parse_file
      headers = nil
      total = file_line_count
      raise ParseError, I18n.t("File has no data") if total < 1

      separator = test_header_i18n
      rows = CSV.new(@file, col_sep: separator).to_enum
      rows.with_index(1).each_slice(BATCH_SIZE) do |batch|
        headers ||= validate_headers(*batch.shift)
        raise ParseError, I18n.t("File has no outcomes data") if batch.empty?

        errors = parse_batch(headers, batch)
        status = {
          errors:,
          progress: (batch.last[1].to_f / total * 100).floor
        }
        yield status
      end
    end

    def parse_batch(headers, batch)
      Account.transaction do

View on GitHub (pinned to 1c9f0bb801)