Skip to main content

Payment Exceptions & Investigations

Overview

Payment exceptions are transactions that cannot be processed automatically and require manual intervention by operations staff. They arise from technical errors, data quality issues, unmatched payments, compliance holds, or network failures.

Effective exception management is critical — unresolved exceptions represent financial risk, regulatory exposure, and customer dissatisfaction.


Types of Payment Exceptions

TypeCauseOwner
Unmatched InboundCreditor account not foundOperations
Sanction HoldPotential match on watchlistCompliance
Fraud HoldHigh fraud scoreFraud team
Duplicate PaymentSame payment submitted twiceOperations
Amount MismatchPayment amount doesn't match expectedOperations
Format ErrorInvalid field values, missing mandatory fieldsTech/Operations
Settlement FailureNetwork or counterparty settlement rejectionOperations
Timed-Out PaymentNo confirmation received within SLAOperations
Suspense Account ItemFunds received, account unidentifiableOperations
Return Not Appliedpacs.004 received but original not foundOperations
Balance DiscrepancyStatement balance doesn't reconcileFinance/Operations
FX Rate DisputeIncorrect exchange rate appliedTreasury/Ops

Exception Lifecycle

Exception Raised (auto or manual)


Categorise & Prioritise
├── HIGH: Regulatory (sanctions) → Compliance team
├── HIGH: Large amount > threshold → Senior ops
├── MEDIUM: Unmatched inbound → Ops queue
└── LOW: Minor format warning → Batch ops


Assign to Owner / Queue


Investigate
├── Check payment details
├── Contact counterparty bank (SWIFT gpi, phone)
├── Contact customer
└── Check upstream systems


Resolve
├── Apply to correct account
├── Return funds (pacs.004)
├── Resubmit corrected payment
├── Write off (if unrecoverable, within authority)
└── Escalate (if above resolution authority)


Close & Log
(outcome, root cause, resolution time)

Unmatched Inbound Payments (Suspense)

The most common exception — an inbound payment arrives but the creditor account cannot be identified:

Inbound pacs.008 received


Account lookup fails:
├── Invalid BSB + account number
├── Account closed
├── PayID not registered
└── Account in different currency


Funds credited to SUSPENSE ACCOUNT
(internal holding account — not customer money yet)


Exception raised in Ops queue


Operations team investigates:
├── Check if account recently closed → identify new account
├── Check if CRN/reference matches known customer
├── Contact sending bank for more details
└── Contact potential beneficiary

├── MATCH FOUND: Transfer from suspense → customer account
│ Send camt.054 to customer

└── NO MATCH after SLA: Return via pacs.004
Reason code: AC01 / AC04

Suspense SLAs

PrioritySLAAction on Breach
> $100,00024 hoursEscalate to senior ops manager
$10,000–$100,0003 business daysTeam lead review
< $10,0005 business daysStandard ops handling
Any amount after 10 daysMandatory returnRegulatory obligation

Sanction Holds

When a payment hits a potential sanctions match:

Payment held by sanctions engine


Compliance analyst receives alert


Review:
├── Is this a true match or false positive?
├── Name similarity? Address? Entity type?
├── Check all aliases and related entities
└── Consult legal/compliance if uncertain

├── FALSE POSITIVE:
│ Document decision + rationale
│ Release payment
│ Update screening rules if needed

└── TRUE MATCH (CONFIRMED HIT):
BLOCK payment permanently
Freeze account (if customer is sanctioned)
File report with AUSTRAC / OFAC / OFSI
DO NOT tip off the customer
Retain records (7 years)

Critical: Sanctions holds must never be resolved by simply releasing the payment without compliance review. The payment must be permanently blocked if it's a true hit.


Timed-Out / Unconfirmed Payments

When a payment is submitted but no pacs.002 confirmation arrives:

Payment submitted to NPP/SWIFT at T+0

No pacs.002 within SLA:
NPP: 60 seconds
RTGS: 15 minutes
SWIFT: 24 hours (business day)


Exception raised: UNCONFIRMED PAYMENT


Investigate:
├── Check NPP/SWIFT tracking (gpi, UETR)
├── Query network operator
├── Check if duplicate already received
└── Contact counterparty bank directly

├── CONFIRMED SETTLED:
│ Apply settlement to internal records
│ Close exception

├── CONFIRMED REJECTED:
│ Reverse debit posting
│ Notify customer

└── STILL UNKNOWN after 2 business days:
Treat as failed
Reverse debit
Notify customer
Pursue recovery if funds confirmed gone

Exception Priority Matrix

SeverityCriteriaResponse SLAEscalation
P1 CriticalRegulatory hold (sanctions), large systemic failure1 hourCompliance Director / CTO
P2 High> $500K unresolved, customer complaint, potential fraud4 hoursOps Manager
P3 Medium> $10K unmatched, settlement fail1 business dayTeam Lead
P4 Low< $10K unmatched, format warning3 business daysStandard queue

Exception Metrics (KPIs)

MetricFormulaTarget
Exception RateExceptions / Total payments< 0.1%
STP RatePayments processed without exception / Total> 99.9%
Avg Resolution TimeTime from raise to close< 4h (P1), < 8h (P2)
Suspense AgingItems > 5 days in suspense0
False Positive RateSanctions false positives / total alerts< 80%
Repeat ExceptionsSame root cause recurringTrending down

Java Spring Implementation

@Service
public class ExceptionManagementService {

public PaymentException raise(
String paymentId,
ExceptionType type,
String reason) {

PaymentException exception = PaymentException.builder()
.paymentId(paymentId)
.type(type)
.reason(reason)
.status(ExceptionStatus.OPEN)
.priority(determinePriority(type, paymentId))
.raisedAt(Instant.now())
.assignedQueue(routeToQueue(type))
.build();

exceptionRepository.save(exception);

// Alert operations team
opsAlertService.alert(exception);

// If P1/P2 — page on-call ops
if (exception.getPriority().isCritical()) {
oncallService.page(exception);
}

return exception;
}

public void resolve(
String exceptionId,
ResolutionAction action,
String resolvedBy,
String notes) {

PaymentException exception = exceptionRepository.findById(exceptionId)
.orElseThrow();

switch (action) {
case APPLY_TO_ACCOUNT -> applyToAccount(exception);
case RETURN_FUNDS -> initiateReturn(exception);
case RESUBMIT -> resubmitPayment(exception);
case WRITE_OFF -> {
authorisationService.checkWriteOffAuthority(
resolvedBy, exception.getAmount());
writeOffService.writeOff(exception);
}
}

exception.setStatus(ExceptionStatus.CLOSED);
exception.setResolvedAt(Instant.now());
exception.setResolvedBy(resolvedBy);
exception.setResolutionNotes(notes);
exceptionRepository.save(exception);

auditService.logResolution(exception);
}
}

public enum ExceptionType {
UNMATCHED_INBOUND,
SANCTION_HOLD,
FRAUD_HOLD,
DUPLICATE_PAYMENT,
SETTLEMENT_FAILURE,
TIMEOUT,
FORMAT_ERROR,
AMOUNT_MISMATCH,
SUSPENSE_ITEM,
RETURN_NOT_APPLIED
}

Root Cause Analysis (RCA)

After resolving exceptions, capture root cause to prevent recurrence:

Root Cause CategoryExamplePrevention
Data qualityInvalid BSB submitted by customerAdd BSB validation in UI
System bugDuplicate submission on timeout retryImplement idempotency keys
ConfigurationStale sanctions list not updatedAutomate list refresh
CounterpartyOther bank sent wrong accountImprove Confirmation of Payee
Process gapNo SLA monitoring for suspenseAdd automated aging alerts