we-promise/sure · error · EnableBankingAccount::Processor::ProcessingError

Failed to set current balance: #{result.error}

Error message

Failed to set current balance: #{result.error}

What it means

EnableBankingAccount::Processor raises ProcessingError when account.set_current_balance(balance) returns an unsuccessful Result. set_current_balance (Account::CurrentBalanceManager#set_current_balance) wraps ANY internal exception into Result(error: e.message) — typical root causes are reconciliation/valuation creation failures or the cache write account.update!(balance:) failing.

Source

Thrown at app/models/enable_banking_account/processor.rb:89

      currency = parse_currency(enable_banking_account.currency) || account.currency || "EUR"

      # Wrap both writes in a transaction so a failure on either rolls back both.
      ActiveRecord::Base.transaction do
        if account.accountable.present? && account.accountable.respond_to?(:available_credit=)
          account.accountable.update!(available_credit: available_credit)
        end

        if skip_balance_update
          account.update!(currency: currency)
        else
          account.update!(currency: currency, cash_balance: balance)

          # Use set_current_balance to create a current_anchor valuation entry.
          # This enables Balance::ReverseCalculator, which works backward from the
          # bank-reported balance — eliminating spurious cash adjustment spikes.
          result = account.set_current_balance(balance)
          raise ProcessingError, "Failed to set current balance: #{result.error}" unless result.success?
        end
      end

      # TODO: pass explicit window_start_date to sync_later to avoid full history recalculation on every sync
      # Currently relies on set_current_balance's implicit sync trigger; window params would require refactor
    end

    # Interprets the reported credit card balance based on the
    # treat_balance_as_available_credit flag.
    # Returns [balance, available_credit, skip_balance_update].
    def interpret_credit_card_balance(account, reported_balance)
      if enable_banking_account.treat_balance_as_available_credit?
        # In this mode the accountable's available_credit field holds the credit
        # limit: the API-provided one, or a user-entered value when the API
        # omits it. Writing the limit back (never the reported balance) keeps
        # the field stable across syncs so a manual limit is never clobbered.
        credit_limit = positive_credit_limit(enable_banking_account.credit_limit) ||
                       positive_credit_limit(account.accountable&.available_credit)

View on GitHub (pinned to e69894adb9)

Solutions

  1. Read the interpolated result.error — it carries the original exception message from CurrentBalanceManager#set_current_balance
  2. Reproduce in console: account.set_current_balance(balance) on the failing account and inspect account.errors.full_messages and the raised cause
  3. Fix the underlying record state (currency, existing valuations, missing associations) that makes valuation/reconciliation creation fail
  4. For credit-card accounts, verify treat_balance_as_available_credit handling in interpret_credit_card_balance — the skip_balance_update path exists precisely to avoid bad balance writes
Defensive patterns

Strategy: try-catch

Validate before calling

result = account.set_current_balance(balance)
result.success? # check before the processor raises; result.error carries the root cause

Try / catch

rescue EnableBankingAccount::Processor::ProcessingError => e; e.message embeds the CurrentBalanceManager error — log it with DebugLogEntry (category 'enable_banking') so partial syncs are diagnosable

Prevention

When it happens

Trigger: During an Enable Banking account import, after account.update!(currency:, cash_balance:), the current-balance manager fails: reconcile_balance or opening-balance delta adjustment raises (invalid amount/date, entry validation), or account.update! trips a validation; the manager converts it to a failed Result, and the processor re-raises as ProcessingError with that message.

Common situations: Bank-reported balances that violate entry validations; accounts in inconsistent state (missing currency/family, conflicting valuations); DB constraints on entries; unusual provider balance values on credit cards.

Related errors


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