{"record":{"id":"34edf7790c740902","repo":"we-promise/sure","slug":"unable-to-parse-transaction-date-date-value-ins","errorCode":null,"errorMessage":"Unable to parse transaction date: #{date_value.inspect}","messagePattern":"Unable to parse transaction date: #(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"app/models/brex_entry/processor.rb","lineNumber":165,"sourceCode":"      case date_value\n      when String\n        if date_value.include?(\"T\") || date_value.include?(\":\")\n          Time.parse(date_value).in_time_zone(account&.family&.timezone).to_date\n        else\n          Date.parse(date_value)\n        end\n      when Integer, Float\n        Time.at(date_value).in_time_zone(account&.family&.timezone).to_date\n      when Time, DateTime\n        date_value.in_time_zone(account&.family&.timezone).to_date\n      when Date\n        date_value\n      else\n        raise ArgumentError, \"Invalid date format: #{date_value.inspect}\"\n      end\n    rescue ArgumentError, TypeError => e\n      Rails.logger.error(\"Failed to parse Brex transaction date '#{date_value}': #{e.message}\")\n      raise ArgumentError, \"Unable to parse transaction date: #{date_value.inspect}\"\n    end\n\n    def extra\n      {\n        brex: {\n          transaction_id: data[:id],\n          account_kind: brex_account.account_kind,\n          type: data[:type],\n          card_id: data[:card_id],\n          transfer_id: data[:transfer_id],\n          expense_id: data[:expense_id],\n          card_transaction_operation_reference_id: data[:card_transaction_operation_reference_id],\n          initiated_at_date: data[:initiated_at_date],\n          posted_at_date: data[:posted_at_date],\n          merchant: BrexAccount.sanitize_payload(data[:merchant])\n        }.compact\n      }\n    end","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/brex_entry/processor.rb#L147-L183","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nBrexEntry::Processor.new(tx, brex_account: ba).process\n\n# after — quarantine unparseable dates before the processor sees them\ndate_value = tx.with_indifferent_access[:posted_at_date].presence || tx.with_indifferent_access[:initiated_at_date].presence\nbegin\n  Date.parse(date_value) if date_value.is_a?(String)\nrescue ArgumentError, TypeError\n  Rails.logger.warn(\"Quarantining Brex tx with bad date: #{date_value.inspect}\")\n  next\nend\nBrexEntry::Processor.new(tx, brex_account: ba).process","handlingStrategy":"validation","validationCode":"def parseable_brex_date?(value)\n  case value\n  when String then begin; Date.parse(value); true; rescue ArgumentError; false; end\n  when Integer, Float, Time, DateTime, Date then true\n  else false # nil, Hash, Array will raise in the processor\n  end\nend","typeGuard":"# Ruby\ndef valid_brex_date_payload?(payload)\n  %w[posted_at_date initiated_at_date].any? do |k|\n    v = payload.with_indifferent_access[k]\n    v.present? && parseable_brex_date?(v)\n  end\nend","tryCatchPattern":"begin\n  processor.process\nrescue ArgumentError => e\n  raise unless e.message.include?(\"Unable to parse transaction date\")\n  Rails.logger.warn(\"Quarantining transaction with unparseable date: #{tx.inspect}\")\n  :skipped\nend","preventionTips":["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."],"tags":["brex","import","date-parsing","payload-validation"],"backgroundTag":"date-parse-failed","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}