we-promise/sure · error · ArgumentError
Unable to parse transaction date: #{date_value.inspect}
Error message
Unable to parse transaction date: #{date_value.inspect} What it means
Raised by BrexEntry::Processor#date (ArgumentError) when posted_at_date/initiated_at_date cannot be converted to a Date: a String that Time.parse/Date.parse rejects, or a type hitting the else branch (nil, Hash, Array). The original error is logged ('Failed to parse Brex transaction date ...') and re-raised as this uniform message including value.inspect.
Source
Thrown at app/models/brex_entry/processor.rb:165
case date_value
when String
if date_value.include?("T") || date_value.include?(":")
Time.parse(date_value).in_time_zone(account&.family&.timezone).to_date
else
Date.parse(date_value)
end
when Integer, Float
Time.at(date_value).in_time_zone(account&.family&.timezone).to_date
when Time, DateTime
date_value.in_time_zone(account&.family&.timezone).to_date
when Date
date_value
else
raise ArgumentError, "Invalid date format: #{date_value.inspect}"
end
rescue ArgumentError, TypeError => e
Rails.logger.error("Failed to parse Brex transaction date '#{date_value}': #{e.message}")
raise ArgumentError, "Unable to parse transaction date: #{date_value.inspect}"
end
def extra
{
brex: {
transaction_id: data[:id],
account_kind: brex_account.account_kind,
type: data[:type],
card_id: data[:card_id],
transfer_id: data[:transfer_id],
expense_id: data[:expense_id],
card_transaction_operation_reference_id: data[:card_transaction_operation_reference_id],
initiated_at_date: data[:initiated_at_date],
posted_at_date: data[:posted_at_date],
merchant: BrexAccount.sanitize_payload(data[:merchant])
}.compact
}
endView on GitHub (pinned to e69894adb9)
Solutions
- Log the inspected value (already logged) and check the payload — most cases are a nil pair or a renamed/nested date field from Brex.
- Pre-validate in the importer: parse the date yourself and skip/quarantine records whose date fields are missing or unparseable, rather than aborting the whole batch.
- If pending transactions legitimately lack posted dates, default them (e.g. to initiated_at_date or Date.current) upstream of the processor.
- Pin explicit formats: prefer Date.strptime(value, '%Y-%m-%d') for ISO dates instead of Date.parse ambiguity.
Example fix
# before
BrexEntry::Processor.new(tx, brex_account: ba).process
# after — quarantine unparseable dates before the processor sees them
date_value = tx.with_indifferent_access[:posted_at_date].presence || tx.with_indifferent_access[:initiated_at_date].presence
begin
Date.parse(date_value) if date_value.is_a?(String)
rescue ArgumentError, TypeError
Rails.logger.warn("Quarantining Brex tx with bad date: #{date_value.inspect}")
next
end
BrexEntry::Processor.new(tx, brex_account: ba).process Defensive patterns
Strategy: validation
Validate before calling
def parseable_brex_date?(value) case value when String then begin; Date.parse(value); true; rescue ArgumentError; false; end when Integer, Float, Time, DateTime, Date then true else false # nil, Hash, Array will raise in the processor end end
Type guard
# Ruby
def valid_brex_date_payload?(payload)
%w[posted_at_date initiated_at_date].any? do |k|
v = payload.with_indifferent_access[k]
v.present? && parseable_brex_date?(v)
end
end Try / catch
begin
processor.process
rescue ArgumentError => e
raise unless e.message.include?("Unable to parse transaction date")
Rails.logger.warn("Quarantining transaction with unparseable date: #{tx.inspect}")
:skipped
end Prevention
- Pre-check posted_at_date/initiated_at_date presence and parseability per transaction; skip and quarantine rather than failing the batch.
- Normalize dates to ISO 8601 at ingestion time (Date.strptime('%Y-%m-%d')) instead of relying on Date.parse heuristics.
- Handle pending transactions (nil posted dates) explicitly with a documented default before they reach the processor.
When it happens
Trigger: data[:posted_at_date] is "2026-13-01" or "not-a-date" (Date.parse raises); both posted_at_date and initiated_at_date are nil (presence || presence → nil → else branch raises 'Invalid date format: nil'); the date arrives as a Hash (e.g. { "date" => "..." }) or an unexpected object type.
Common situations: Upstream schema change where dates became nested objects; transactions in an unusual state (pending with no timestamps) yielding nil dates; locale-dependent strings like "31/12/2026" that Time.parse misreads or rejects depending on Date._parse behavior.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/34edf7790c740902.
Report an issue: GitHub.