instructure/canvas-lms · error · ParseError
File has no outcomes data
Error message
File has no outcomes data
What it means
In Outcomes::CsvImporter#parse_file, after the first batch of rows is consumed for header validation, the remaining batch is checked; if it is empty the file contained a header but no outcome rows, so ParseError 'File has no outcomes data' is raised. This distinguishes a header-only CSV from the completely empty case.
Solutions
- Add at least one outcome data row beneath the header and re-import.
- Verify the header row matches the expected outcomes import format so data rows are not misparsed.
- Check line endings/encoding (e.g. BOM or CR-only files) that could prevent data rows from being read.
- Warn users in the UI when the selected file has only one line before submitting.
Example fix
// before (header only) "title,vendor_guid,display_name\n" // after "title,vendor_guid,display_name\nMy Outcome,vo-1,My Outcome\n"
Defensive patterns
Strategy: validation
Validate before calling
rows = CSV.read(path) raise 'header-only CSV' if rows.size < 2
Type guard
def has_data_rows?(path) rows = CSV.read(path) rows.is_a?(Array) && rows.size > 1 end
Try / catch
begin importer.run rescue Outcomes::CsvImporter::ParseError => e flash[:error] = e.message # 'File has no outcomes data' end
Prevention
- Require at least one data row below the header in templates.
- Warn users when the selected file has only one line.
- Check line endings/encoding so data rows are not skipped during parsing.
When it happens
Trigger: Importing an outcomes CSV that contains only the header row (or fewer than BATCH_SIZE rows where the only row was consumed as the header), so the first batch.shift empties the batch.
Common situations: Users upload the untouched CSV template with headers but never filled in data rows; a filter/export step dropped all data rows; row endings/encoding caused all data rows to be skipped leaving only the header.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Database error ( )
- File has no data
- Invalid CSV File
- Cannot modify outcome from another context
- Cyclic reference detected when importing
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/a6e6d5fd35f63b01.
Report an issue: GitHub.
Appendix: source
Thrown at lib/outcomes/csv_importer.rb:85
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
results = batch.map do |row, line|
utf8_row = row.map(&method(:check_encoding))
import_row(headers, utf8_row) unless utf8_row.all?(&:blank?)
[]
rescue ParseError, InvalidDataError => e
[[line, e.message]]View on GitHub (pinned to 1c9f0bb801)