Suite Utils
Back to Blog
NetSuite TipsSep 21, 2026 • 6 min read

Fix NetSuite EFT Bank Detail Mismatch in XML Output

The EFT Bill Payments page (Transactions > Payments > EFT Bill Payments) builds a payment batch from selected vendor bills.

Sarah Jenkins, CPASarah Jenkins, CPAPrincipal Finance Automation Specialist
Fix NetSuite EFT Bank Detail Mismatch in XML Output
On this page

When you generate an Electronic Bank Payment file for multiple vendors with different payment methods, say NEFT for one vendor and RTGS for another, NetSuite's XML output sometimes repeats the first vendor's bank details across every payment in the batch. The root cause is straightforward: your FreeMarker template is using payment_index as a proxy for vendor identity, but NetSuite does not guarantee that the payment array order matches the vendor sequence or internal ID order. The fix is to key bank detail lookups off the payment record's actual vendor reference, not the loop index.

Why the Index-Based Approach Fails

The EFT Bill Payments page (Transactions > Payments > EFT Bill Payments) builds a payment batch from selected vendor bills. Each payment in that batch carries a vendor field pointing to the payee's entity record. However, the FreeMarker context exposes payments as a simple array (payments or paymentList), and many templates iterate with <#list payments as payment> while simultaneously trying to pull bank details from a parallel bankDetails array using payment_index.

NetSuite's batch assembly logic sorts payments by internal ID, due date, or payment method, not by the order you checked them on the screen. If Vendor A (NEFT) has internal ID 1200 and Vendor B (RTGS) has 1150, the batch may place Vendor B first. Your template then reads bankDetails[0] for the first payment, which belongs to Vendor B, but bankDetails[0] was populated from Vendor A's record. The result: Vendor B's payment carries Vendor A's account number, IFSC code, and beneficiary name.

The control here is binding each payment to its vendor's bank details at the record level, not the array level.

Correct FreeMarker Pattern: Use the Payment Object's Vendor Reference

Each payment object in the FreeMarker context includes a vendor property (or entity depending on your template version) that references the vendor record. The template context also includes a bankDetails map keyed by vendor internal ID, use that instead of a parallel array.

<#list payments as payment>
  <#assign vendorId = payment.vendor?string>
  <#assign vendorBank = bankDetails[vendorId]>
  <#if vendorBank??>
    <payment>
      <beneficiaryName>${vendorBank.beneficiaryName}</beneficiaryName>
      <accountNumber>${vendorBank.accountNumber}</accountNumber>
      <ifscCode>${vendorBank.ifscCode}</ifscCode>
      <paymentMethod>${payment.paymentmethod}</paymentMethod>
      <amount>${payment.amount}</amount>
    </payment>
  <#else>
    <#-- Log or handle missing bank details -->
  </#if>
</#list>

This pattern uses the vendor ID from each payment to look up the correct bank detail object directly. No index math, no order assumptions.

Handling Multiple Bank Details Per Vendor

Some vendors maintain separate accounts for NEFT and RTGS. The bankDetails map can include a composite key (vendor ID + payment method) when the payment file format is configured to pass method-specific details. In the template:

<#assign lookupKey = payment.vendor + '_' + payment.paymentmethod>
<#assign vendorBank = bankDetails[lookupKey]>
<#if vendorBank??>
  <accountNumber>${vendorBank.accountNumber}</accountNumber>
  <ifscCode>${vendorBank.ifscCode}</ifscCode>
<#else>
  <#-- Fallback to default bank detail for this vendor -->
  <#assign vendorBank = bankDetails[payment.vendor?string]>
</#if>

This requires the payment file format's field mapping to include the payment method in the bank detail key. Configure this in the format definition (see Configuration Checklist below).

Configuration Checklist Before You Touch the Template

  1. Install the Electronic Bank Payments SuiteApp Electronic Bank Payments is delivered as a SuiteApp bundle. Install it via SuiteApps > SuiteBundles > Search & Install Bundles (search "Electronic Bank Payments"). This adds the feature, roles, and base payment formats. NetSuite Connector

  2. Define Payment File Formats for NEFT and RTGS Setup > Accounting > Payment File Formats > New

  • Format Type: XML
  • File Extension: .xml
  • Assign each format to the appropriate Payment Method (create NEFT and RTGS as separate payment methods under Setup > Accounting > Payment Methods)
  • In the format's Field Mapping sublist, map bankDetails using a composite key of vendorInternalId_paymentMethod so the template receives method-specific bank data NetSuite Connector
  1. Set Vendor Bank Details Open each vendor record > Bank Details sublist > Add/Edit
  • Mark one line Default (checkbox isdefault)
  • If using method-specific accounts, add separate lines and note which supports NEFT vs RTGS, the format mapping uses this to build the composite key
  1. Assign Payment Method on Vendor Bills When creating or editing a vendor bill, set Payment Method to NEFT or RTGS. This value flows to the payment record and becomes available in the template as payment.paymentmethod.

  2. Test with a Two-Vendor Batch On the EFT Bill Payments page, select one NEFT bill and one RTGS bill from different vendors. Generate the file and inspect the XML, each <payment> block should show the correct beneficiary, account number, and IFSC.

Common Pitfall: Trying to Load Records Inside FreeMarker

FreeMarker templates in Electronic Bank Payments cannot call record.load() or search.load(). Those are SuiteScript 2.1 APIs and are not available in the template context. The template only receives the data structure passed by the payment file generation engine, primarily payments, bankDetails, companyBank, and format-specific variables.

If your batch size exceeds what the standard bankDetails map covers (rare, but possible with custom filtering), the solution is a SuiteScript 2.1 map/reduce script that pre-processes the payment batch and writes a custom JSON parameter the template can read. Deploy the script, add a script parameter (e.g., custscript_bank_detail_map), and reference it in the template as runtime.getCurrentScript().getParameter({name: 'custscript_bank_detail_map'}). System Notes Guide

For 95% of implementations, the standard bankDetails map keyed by vendor ID (or vendor ID + payment method) is sufficient and requires no scripting.

What to Verify After Deployment

  • Generate a test file with three vendors: one NEFT-only, one RTGS-only, one with both methods defined. Confirm each payment block reflects the correct account.
  • Check the Payment File Administration page (Transactions > Payments > Payment File Administration) for the generated file. Download and open in a text editor, do not rely on the preview pane.
  • If the bank rejects the file, review the Electronic Bank Payments Error Codes list (Setup > Accounting > Payment File Formats > Error Codes). Common rejections: invalid IFSC length (must be 11 characters), beneficiary name exceeding 40 characters, or account number with special characters.

The mismatch disappears once the template stops treating payment_index as a vendor identifier. Key every lookup to payment.vendor (or payment.entity) via the bankDetails map and the problem resolves permanently, no matter how NetSuite reorders the batch.

About the author

Put these ideas to work.

Suite Utils builds small NetSuite tools that fix the specific thing breaking your day. Each one runs as a native SuiteScript SuiteApp inside your account. No sales call, no onboarding.

Browse the Tools

Enjoyed this one?

Get NetSuite tips like this in your inbox. No spam. Practical guides only.

Keep reading