instructure/canvas-lms · error · DataFormatError

Database error ( )

Error message

Database error (%{err})

What it means

Outcomes::CsvImporter#run rescues ActiveRecord::StatementInvalid raised during parse_file (e.g. database constraint violations, invalid UTF-8 bytes rejected by the DB, or timeouts while inserting outcome batches) and re-raises it as DataFormatError with 'Database error (%{err})' embedding the DB error message. It maps low-level DB failures during CSV import into the importer's public error type.

Solutions

  1. Read the embedded %{err} message to identify the failing statement/constraint.
  2. Fix the offending rows (encoding, duplicates, value lengths) in the CSV and re-import.
  3. Validate the file is valid UTF-8 before import (iconv/encoding check) when the DB error mentions invalid byte sequences.
  4. Check DB logs and connectivity if the statement failure is infrastructural rather than data-driven.

Example fix

// before
File.read('outcomes.csv') # may contain invalid UTF-8
// after
content = File.read('outcomes.csv').force_encoding('UTF-8')
raise 'not UTF-8' unless content.valid_encoding?
Defensive patterns

Strategy: try-catch

Validate before calling

content = File.read(path)
abort 'invalid encoding' unless content.force_encoding('UTF-8').valid_encoding?

Type guard

def db_safe_csv?(path)
  c = File.read(path).force_encoding('UTF-8')
  c.valid_encoding?
end

Try / catch

begin
  importer.run
rescue Outcomes::CsvImporter::DataFormatError => e
  logger.error("import db error: #{e.message}")
end

Prevention

When it happens

Trigger: An outcomes CSV import where a batch insert inside parse_file triggers ActiveRecord::StatementInvalid — bad data violating DB constraints, encoding the database refuses, or statement failures on very large batches.

Common situations: Importing CSVs with invalid UTF-8 into a UTF-8 database; duplicate keys on outcome unique indexes; overly long values exceeding column limits; DB connectivity/timeout issues during a long import.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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

Appendix: source

Thrown at lib/outcomes/csv_importer.rb:67

      @import = import
      @file = file
    end

    delegate :context, to: :@import

    def run(&)
      status = { progress: 0, errors: [] }
      yield status

      file_errors = []
      begin
        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?

View on GitHub (pinned to 1c9f0bb801)