Sepa JS XML includes comprehensive validation to ensure your SEPA XML files meet all requirements. This guide covers validation options, constraints, and error handling.
Validation options
You can control validation behavior with the Options interface (from index.ts:10-26):
import { createSepaXML , type Options } from 'sepa-js-xml' ;
const options : Options = {
prettyPrint: false , // Format XML with indentation
checkIBAN: true , // Validate IBAN codes
checkBIC: true // Validate BIC codes
};
const xml = createSepaXML ( sepaData , options );
Default values
From the source code (index.ts:139):
options = {
prettyPrint: false ,
checkBIC: true ,
checkIBAN: true
}
All validation is enabled by default . You must explicitly disable it if needed.
IBAN validation
How it works
IBAN validation uses the ibantools library (from index.ts:7):
import { isValidIBAN } from "ibantools" ;
Enabling/disabling
Enabled (default)
Disabled
const xml = createSepaXML ( sepaData , {
checkIBAN: true // Default behavior
});
The library validates all IBAN codes and throws an error if invalid. const xml = createSepaXML ( sepaData , {
checkIBAN: false // Skip IBAN validation
});
Use this for testing or when you validate IBANs elsewhere. Disabling IBAN validation may result in files rejected by your bank.
IBAN validation errors
From the source code (index.ts:219-223), IBAN validation errors include the position index:
if ( options ?. checkIBAN && ! isValidIBAN ( item . iban )) {
throw new Error (
`sepaData.positions[ ${ index } ].iban is not valid ( ${ item . iban } )` ,
);
}
const xml = createSepaXML ({
id: "Test" ,
creationDate: new Date (),
initiatorName: "Test" ,
positions: [{
name: "Test" ,
iban: "INVALID" , // Invalid IBAN
bic: "SSKMDEMM" ,
id: "123" ,
requestedExecutionDate: new Date (),
payments: []
}]
});
// Error: sepaData.positions[0].iban is not valid (INVALID)
The ibantools library supports all SEPA country IBANs:
DE - Germany (22 characters)
FR - France (27 characters)
IT - Italy (27 characters)
ES - Spain (24 characters)
NL - Netherlands (18 characters)
BE - Belgium (16 characters)
AT - Austria (20 characters)
AT, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FR, GB, GI, GR, HR, HU, IE, IS, IT, LI, LT, LU, LV, MC, MT, NL, NO, PL, PT, RO, SE, SI, SK, SM, VA
BIC validation
How it works
BIC validation also uses ibantools (from index.ts:7):
import { isValidBIC } from "ibantools" ;
Enabling/disabling
Enabled (default)
Disabled
const xml = createSepaXML ( sepaData , {
checkBIC: true // Default behavior
});
The library validates all BIC codes and throws an error if invalid. const xml = createSepaXML ( sepaData , {
checkBIC: false // Skip BIC validation
});
Useful when:
Using PAIN version 03 (BIC optional)
Testing with dummy data
BIC validation done elsewhere
BIC validation errors
From the source code (index.ts:226-230):
if ( options ?. checkBIC && ( item . bic ? ! isValidBIC ( item . bic ) : bicOptional )) {
throw new Error (
`sepaData.positions[ ${ index } ].bic is not valid ( ${ item . bic } )` ,
);
}
const xml = createSepaXML ({
id: "Test" ,
creationDate: new Date (),
initiatorName: "Test" ,
positions: [{
name: "Test" ,
iban: "DE02701500000000594937" ,
bic: "INVALID" , // Invalid BIC
id: "123" ,
requestedExecutionDate: new Date (),
payments: []
}]
});
// Error: sepaData.positions[0].bic is not valid (INVALID)
Valid BIC codes:
8 characters : SSKMDEMMXXX
11 characters : SSKMDEMM (branch code optional)
Format: AAAABBCCDDD where:
AAAA = Bank code
BB = Country code
CC = Location code
DDD = Branch code (optional)
BIC optional scenarios
From the source code (index.ts:225, index.ts:374-376), BIC is optional for:
Direct debits (creditor side) - all versions
Credit transfers (both sides) - PAIN version 03 only
// BIC optional - no error even with checkBIC: true
const xml = createSepaXML ({
painVersion: "pain.001.001.03" ,
// ... other fields
positions: [{
iban: "DE02701500000000594937" ,
// bic not provided - OK for version 03
payments: [{
iban: "DE89370400440532013000"
// bic not provided - OK for version 03
}]
}]
}, {
checkBIC: true // Still validates if BIC is provided
});
Length constraints
The library enforces maximum length constraints (from index.ts:399-403):
function checkLength ( value : string , name : string , length : number ) {
if ( value . length > length ) {
throw new Error ( `Max length for ${ name } is ${ length } ( ${ value } )` );
}
}
Field length limits
Maximum: 35 characters Applies to:
sepaData.id (from index.ts:155)
positions[].id (from index.ts:217)
payments[].id (from index.ts:318-322)
Maximum: 70 characters Applies to:
sepaData.initiatorName (from index.ts:156)
positions[].name (from index.ts:218)
payments[].name (from index.ts:323-327)
Length validation errors
ID too long
Name too long
Valid lengths
const xml = createSepaXML ({
id: "123456789012345678901234567890123456" , // 36 chars - too long!
creationDate: new Date (),
initiatorName: "Test" ,
positions: []
});
// Error: Max length for sepaData.id is 35 (123456789012345678901234567890123456)
Error handling
Try-catch pattern
Wrap createSepaXML in a try-catch block:
import { createSepaXML } from 'sepa-js-xml' ;
try {
const xml = createSepaXML ({
id: "MSG001" ,
creationDate: new Date (),
initiatorName: "My Company" ,
positions: [{
id: "PMT001" ,
name: "My Company" ,
iban: "DE02701500000000594937" ,
bic: "SSKMDEMM" ,
requestedExecutionDate: new Date (),
payments: [{
id: "TXN001" ,
name: "Customer A" ,
iban: "INVALID_IBAN" ,
amount: 100.00 ,
remittanceInformation: "Payment"
}]
}]
});
console . log ( "XML generated successfully" );
return xml ;
} catch ( error ) {
console . error ( "Validation failed:" , error . message );
// Handle the error appropriately
// Error: sepaData.positions[0].payments[0].iban is not valid (INVALID_IBAN)
}
Common validation errors
Error: sepaData.positions[0].iban is not valid (INVALID)
Cause : IBAN fails checksum or format validationSolution : Verify IBAN with customer or use a valid IBAN from your bank
Error: sepaData.positions[0].bic is not valid (INVALID)
Cause : BIC doesn’t match expected formatSolution : Use 8 or 11 character BIC code, or omit for PAIN v03
Error: Max length for sepaData.id is 35 (very_long_identifier_that_exceeds_the_limit)
Cause : Field exceeds maximum allowed lengthSolution : Truncate the value to fit within the limit
Missing end-to-end reference
Error: sepaData.positions[0].payments[0].end2endReference is required with the selected pain version
Cause : Using PAIN v03 without end-to-end reference (from index.ts:338-341)Solution : Add end2endReference field or use PAIN v02
Validation in tests
From the test file (index.test.ts:106-123, 125-143, 145-163):
Test ID length
Test IBAN validation
Test BIC validation
test ( "check id error" , () => {
expect (() =>
createSepaXML ({
id: "123456789123456789123456789123456789" , // 36 chars
creationDate: new Date (),
initiatorName: "Test" ,
positions: [],
}, {
checkIBAN: true ,
checkBIC: true ,
})
). toThrow (
"Max length for sepaData.id is 35 (123456789123456789123456789123456789)"
);
});
Validation checklist
Before generating SEPA XML:
Validate IBANs
Ensure all IBANs are valid for their country:
Correct length
Valid checksum
Proper country code
Validate BICs
Ensure all BICs are valid or omitted when optional:
8 or 11 characters
Valid format
Optional for PAIN v03 and direct debits
Check field lengths
Ensure no field exceeds maximum length:
IDs: 35 characters
Names: 70 characters
Verify required fields
Ensure all required fields are provided:
end2endReference for PAIN v03 credit transfers
mandateId and mandateSignatureDate for direct debits
Test with validation enabled
Always test with default validation enabled: createSepaXML ( data ) // Uses default validation
Best practices
Keep validation enabled Always use default validation unless you have a specific reason to disable it.
Validate early Validate IBANs and BICs when collecting user input, not just when generating XML.
Handle errors gracefully Wrap XML generation in try-catch and provide user-friendly error messages.
Test thoroughly Test with both valid and invalid data to ensure proper error handling.
Next steps
Examples See complete examples with validation
Credit transfers Learn about credit transfer requirements
Direct debits Learn about direct debit requirements
API Reference View complete API documentation