Skip to content

Troubleshooting

The readers throw a ParseException on the first line they cannot parse. The message tells what failed:

Message Cause
Unable to find a parser for the line :
"…"
The line is not 120 (CFONB 120) or 240 (CFONB 240) characters long, or its record code is unknown: CFONB 120 supports 01, 04, 05 and 07, CFONB 240 31, 34 and 39
Regex does not match the line "…" A field holds unexpected characters: letters in a numeric field, a date or an amount, an invalid sign character
The value of key "…" is not a string A required field is blank, e.g. the currency of a balance, or the reference of an operation in strict mode
The value of key "…" is not numeric A numeric field is blank, e.g. the number of decimals of an amount
Unable to attach a detail for operation with code … A 05 detail line with no 04 operation before it in its statement
Unable to attach the operation with code … dated …: missing "01" old balance record before it A 04 operation line outside a statement: before the first 01 old balance, or after a 07 new balance without a new 01 old balance
Unable to close a statement with the "07" new balance of account … dated …: missing "01" old balance record before it A 07 new balance line with no open statement: before the first 01 old balance, or right after another 07 new balance
Unable to open a statement with the "01" old balance of account … dated …: the statement of account … opened on … has no "07" new balance record A 01 old balance line while a statement is still open: the 07 new balance of that statement is missing
Unable to close the statement of account … opened on …: missing "07" new balance record at the end of the file The last statement has no 07 new balance: the file is likely truncated
Unable to parse date "…" A date that does not exist: day 00 or 32, month 00 or 13, 31 April, 29 February of a non-leap year
Unable to parse date "000000": the date is zero-filled (empty), but this field is mandatory A mandatory date written as zeros, e.g. the value date of an operation: some banks write a date they do not have this way
Unable to attach the transaction with sequence number …: missing "31" header record before it A 34 transaction line outside a transfer: before the first 31 header, or after a 39 total without a new 31 header
Unable to attach the total with sequence number …: missing "31" header record before it A 39 total line outside a transfer: before the first 31 header, or after a 39 total without a new 31 header
Unable to start a transfer with the "31" header record of sequence number …: the previous transfer has no "39" total record A 31 header line while a transfer is still open: the 39 total of that transfer is missing
Unable to close the transfer of the "31" header record of sequence number …: missing "39" total record at the end of the file The last transfer has no 39 total: the file is likely truncated
troubleshooting-error.php
<?php
use Silarhi\Cfonb\Cfonb120Reader;
use Silarhi\Cfonb\Exceptions\ParseException;
$reader = new Cfonb120Reader();
// A line cut to 119 characters: no parser supports it
$content = substr(file_get_contents('statements.txt'), 0, 119);
try {
$reader->parse($content);
} catch (ParseException $e) {
echo 'Parse error: ', $e->getMessage(), "\n";
}
Output
Parse error: Unable to find a parser for the line :
"0110278 02204EUR2 00012345603 060420 0000000166956E060420070420 "
use Silarhi\Cfonb\Cfonb120Reader;
use Silarhi\Cfonb\Exceptions\ParseException;
$reader = new Cfonb120Reader();
try {
$statements = $reader->parse($content);
} catch (ParseException $e) {
// Common issues:
// - Invalid line length (should be 120 characters)
// - Unknown record code (CFONB 120 supports 01, 04, 05 and 07)
// - Malformed line format
// - Invalid, out-of-range (e.g. day 32) or zero-filled date
// - Records out of order (e.g. a missing "07" new balance)
// - Invalid amount format
echo "Parse error: " . $e->getMessage() . "\n";
// Non-strict mode only tolerates blank operation references,
// any other error is still thrown
$statements = $reader->parse($content, false);
}

Non-strict mode only tolerates blank operation references: see strict mode.

To reject a file before parsing it, e.g. to tell an uploader it is not a CFONB 120 statement:

troubleshooting-validate.php
<?php
use Silarhi\Cfonb\Cfonb120Reader;
function validateCfonbFormat(string $content): bool
{
// Normalize line endings, but keep trailing spaces: they are part of the 120 characters
$lines = explode("\n", trim(str_replace(["\r\n", "\r"], "\n", $content), "\n"));
foreach ($lines as $line) {
if ('' === $line) {
continue;
}
if (Cfonb120Reader::LINE_LENGTH !== strlen($line)) {
return false;
}
if (!in_array(substr($line, 0, 2), ['01', '04', '05', '07'], true)) {
return false;
}
}
return true;
}
var_dump(validateCfonbFormat(file_get_contents('statements.txt')));
var_dump(validateCfonbFormat(file_get_contents('transfers.txt')));
Output
bool(true)
bool(false)

\n, \r\n and \r (classic Mac OS, since 6.5) line endings are read alike, as are files with no line breaks at all, split every 120 (or 240) characters. Empty lines are ignored, but not a line of spaces or tabs: it throws Unable to find a parser for the line.

troubleshooting-line-endings.php
<?php
use Silarhi\Cfonb\Cfonb120Reader;
$reader = new Cfonb120Reader();
$content = file_get_contents('statements.txt');
$variants = [
'LF' => $content,
'CRLF' => str_replace("\n", "\r\n", $content),
'CR' => str_replace("\n", "\r", $content),
'No line breaks' => str_replace("\n", '', $content),
];
foreach ($variants as $name => $variant) {
echo sprintf("%s: %d statements\n", $name, count($reader->parse($variant)));
}
Output
LF: 3 statements
CRLF: 3 statements
CR: 3 statements
No line breaks: 3 statements

The trailing spaces of a line are part of its 120 or 240 characters: an editor, a transfer tool or a trim() removing them makes the line too short. Normalize line endings with str_replace(["\r\n", "\r"], "\n", $content), never with trim() on each line.