we-promise/sure · error · ArgumentError
Unable to parse transaction date
Error message
Unable to parse transaction date
What it means
AkahuEntry::Processor#date converts data[:date] to a Date by type: ISO-ish strings go through Time.parse then in_time_zone(family timezone); epoch Integer/Float through Time.at; Time/DateTime re-zoned; Date passed through. Two failure layers produce the same user-visible ArgumentError("Unable to parse transaction date"): (a) an unparseable String raises inside Time.parse; (b) an unknown type hits the internal raise "Invalid date format". Both are rescued (ArgumentError, TypeError) — TypeError covers nil-adjacent arithmetic like Time.at(nil) — logged, and re-raised with the stable message. Timezone lookup failures (family.timezone nil/bogus) also surface here since in_time_zone is inside the rescue.
Source
Thrown at app/models/akahu_entry/processor.rb:192
when String
if value.include?("T") || value.include?(":")
Time.parse(value).in_time_zone(account&.family&.timezone).to_date
else
Date.parse(value)
end
when Integer, Float
Time.at(value).in_time_zone(account&.family&.timezone).to_date
when Time, DateTime
value.in_time_zone(account&.family&.timezone).to_date
when Date
value
else
Rails.logger.error("Akahu transaction has invalid date value")
raise ArgumentError, "Invalid date format"
end
rescue ArgumentError, TypeError => e
Rails.logger.error("Failed to parse Akahu transaction date: #{e.class}")
raise ArgumentError, "Unable to parse transaction date"
end
def extra_metadata
{
"akahu" => {
"pending" => pending?,
"type" => data[:type],
"category" => category_data[:name],
"category_id" => category_data[:_id].presence || category_data[:id],
"category_group" => category_group_name,
"reference" => meta_data[:reference],
"particulars" => meta_data[:particulars],
"code" => meta_data[:code],
"other_account" => meta_data[:other_account]
}.compact
}
end
View on GitHub (pinned to e69894adb9)
Solutions
- Look at the logged line "Failed to parse Akahu transaction date" plus the raw transaction (log data[:date].inspect) to identify whether it's the value or the type
- Ensure the account's family has a valid timezone (account&.family&.timezone) — a nil timezone poisons every date conversion for that family
- If the feed genuinely changed format, extend the String branch to try Date.parse or explicit formats before raising
- Quarantine the malformed transaction and let the sync continue — one bad date shouldn't block the whole import
Example fix
# before
def date
value = data[:date]
case value
when String
Time.parse(value).in_time_zone(account&.family&.timezone).to_date # "garbage" -> ArgumentError
...
# after
def date
value = data[:date]
case value
when String
tz = account&.family&.timezone || "UTC"
(Time.parse(value) rescue (return nil)).in_time_zone(tz).to_date
when Integer, Float
Time.at(value).in_time_zone(account&.family&.timezone || "UTC").to_date
...
end
# caller: skip/save-without-date when nil is returned Defensive patterns
Strategy: validation
Validate before calling
# Before processing a transaction
def valid_date_payload?(value)
case value
when Date, Time, DateTime then true
when Integer, Float then true
when String
begin; !!Time.parse(value); rescue ArgumentError; false; end
else false
end
end
abort_row unless valid_date_payload?(data[:date]) && account&.family&.timezone.present? Type guard
def akahu_date_convertible?(value) case value when Date, Time, DateTime, Integer, Float then true when String then (Time.parse(value) rescue false) ? true : false else false end end
Try / catch
rescue ArgumentError => e
if e.message == "Unable to parse transaction date"
# skip/quarantine the row; log value + family timezone; continue sync
next
else
raise
end
end Prevention
- Ensure every family has a timezone set before importing (nil timezone poisons all dates)
- Validate feed dates at the boundary (ISO 8601 preferred) and quarantine bad rows
- Log data[:date].inspect in the rescue so failures are diagnosable
- Cover date-type variants (string/epoch/date) in processor tests, including one bad row
When it happens
Trigger: Akahu sends date as "31/02/2024" (impossible date) or "FY24-Q1" (garbage); a schema change delivers date as a Hash; the account's family has no timezone set making in_time_zone raise; epoch passed as a String containing digits (String branch -> Time.parse("1690000000") succeeds but a String "abc123" fails); VCR cassette hand-edited with a malformed date field.
Common situations: Bank/feed data glitches producing one corrupt row; API version changes flipping date from ISO 8601 to another format; sandbox accounts with placeholder data; multi-timezone setups where family.timezone is nil because the family record predates the timezone column.
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
- Invalid transaction amount
- Enable Banking session is not valid or has expired
- bad_request
- unauthorized
- request_failed
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/8106bba48d7efd3d.
Report an issue: GitHub.