we-promise/sure · error · AccountImport::OpeningBalanceError

Invalid date format for '#{row.date}': #{e.message}

Error message

Invalid date format for '#{row.date}': #{e.message}

What it means

During an account import (CSV), each row may carry an opening-balance date parsed with Date.strptime(row.date, date_format) using the format the user selected for the import. When strptime cannot match the cell against that format it raises ArgumentError, which the importer wraps in AccountImport::OpeningBalanceError with the offending value and strptime's message. The error is row-specific: the amount/account parts may be fine; only the date cell and the declared format disagree.

Source

Thrown at app/models/account_import.rb:27

        account = family.accounts.build(
          name: row.name,
          balance: row.amount.to_d,
          currency: row.currency,
          accountable: accountable_class.new,
          import: self
        )

        account.save!

        manager = Account::OpeningBalanceManager.new(account)

        # Parse date if provided, otherwise use default
        balance_date = if row.date.present?
          begin
            Date.strptime(row.date, date_format)
          rescue ArgumentError => e
            raise OpeningBalanceError, "Invalid date format for '#{row.date}': #{e.message}"
          end
        else
          nil
        end

        result = manager.set_opening_balance(balance: row.amount.to_d, date: balance_date)

        # Re-raise since we should never have an error here
        if result.error
          raise OpeningBalanceError, result.error
        end
      end
    end
  end

  def mapping_steps
    [ Import::AccountTypeMapping ]
  end

View on GitHub (pinned to e69894adb9)

Solutions

  1. Re-run the import with the date format that matches the actual column (open the CSV in a text editor, not Excel, to see raw cells)
  2. Fix or delete the offending date cell(s) — the error message names the exact value; search the file for it
  3. Normalize dates upstream: preprocess the CSV to ISO 8601 (YYYY-MM-DD) and pick that format in the UI
  4. If exporting from Excel, format the column as text or as the exact pattern chosen in the importer before saving

Example fix

# before
Date.strptime("2024-01-31", "%d-%m-%Y")
# => ArgumentError: invalid date -> OpeningBalanceError "Invalid date format for '2024-01-31': ..."

# after
Date.strptime("2024-01-31", "%Y-%m-%d") # pick the matching format in the import UI
# or leave the date column blank to use the default (balance_date = nil path)
Defensive patterns

Strategy: validation

Validate before calling

# Before running the import, dry-run the date column
fmt = import.date_format # e.g. "%d-%m-%Y"
bad = csv_rows.reject { |r| r.date.blank? || Date.strptime(r.date, fmt) rescue false }
abort "#{bad.size} rows fail the selected format: #{bad.first(3).map(&:date)}" if bad.any?

Type guard

def parseable_date?(cell, format)
  return true if cell.to_s.strip.empty?
  !!Date.strptime(cell.to_s.strip, format)
rescue ArgumentError, TypeError
  false
end

Try / catch

rescue AccountImport::OpeningBalanceError => e
  # e.message names the exact offending value; fix that row/format and re-import
  render json: { error: e.message }, status: :unprocessable_entity
end

Prevention

When it happens

Trigger: Selecting %d-%m-%Y in the import UI while the CSV column contains 2024-01-31 (ISO); a cell with a textual month ("Jan 31, 2024") against %m/%d/%Y; two-digit year vs four-digit format mismatch (%y vs %Y); stray whitespace or a Unicode non-breaking space in the date cell; an Excel export producing 01/02/2024 while the format was set for a different regional order.

Common situations: Bank CSV exports whose date order differs from the user's locale assumption (US mm/dd vs EU dd/mm); switching banks and reusing the previous import settings; spreadsheets that silently reformat date columns on save; a single malformed row in an otherwise good export (one bank glitch row blocks the import since save! and the raise abort the run).

Related errors


AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21). Data as JSON: /api/errors/e890ccd691d7c6f7. Report an issue: GitHub.