unopim/unopim · error · InvalidArgumentException
wrong_columns_number
wrong_columns_number
Error message
wrong_columns_number
What it means
Thrown as \InvalidArgumentException with message 'wrong_columns_number' (AbstractImporter::ERROR_CODE_COLUMNS_NUMBER) while iterating an import source. AbstractSource::current() compares count(currentRowData) against totalColumns, the column count taken from the header row; a data row whose field count differs aborts the import. If the row also contains a stray single quote (foundWrongQuoteFlag), 'wrong_quotes' is thrown instead, so this error means the ragged row is NOT quote-related.
Source
Thrown at packages/Webkul/DataTransfer/src/Helpers/Sources/AbstractSource.php:64
/**
* Checks if current position is valid
*/
public function valid(): bool
{
return $this->currentRowNumber !== -1;
}
/**
* Read next line from source
*/
public function current(): array
{
$row = $this->currentRowData;
if (count($row) !== $this->totalColumns) {
throw_if($this->foundWrongQuoteFlag, \InvalidArgumentException::class, AbstractImporter::ERROR_CODE_WRONG_QUOTES);
throw new \InvalidArgumentException(AbstractImporter::ERROR_CODE_COLUMNS_NUMBER);
}
return array_combine($this->columnNames, $row);
}
/**
* Read next line from source
*/
public function next(): void
{
$this->currentRowNumber++;
$row = $this->getNextRow();
if ($row === false || $row === []) {
$this->currentRowData = [];
$this->currentRowNumber = -1;View on GitHub (pinned to c27a402253)
Solutions
- Open the file at the row number reported by getCurrentRowNumber() and make its field count match the header (same number of delimiters, quote any value containing the delimiter).
- Verify the delimiter passed to the CSV source matches the file's real separator (the constructor rejects mismatches, but a header-only match with ragged body rows still slips through fgetcsv).
- Re-export from the source system with consistent quoting, or normalize the file with a pre-pass that pads/truncates rows to header width.
- If your data legitimately contains quotes, fix those values first: rows with stray single quotes raise the separate wrong_quotes error and mask this one.
Example fix
// before (row: "SKU1,Red, Shirt, XL" -> 4 fields vs 3-column header) SKU1,"Red, Shirt",XL // after: value containing the delimiter is quoted, field count matches header SKU1,"Red, Shirt",XL
Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate the CSV before handing it to the importer source
$path = Storage::disk('private')->path($filePath);
$handle = fopen($path, 'r');
$header = fgetcsv($handle, 0, $delimiter, escape: '\\');
$width = count($header);
$badRows = [];
$line = 1;
while (($row = fgetcsv($handle, 0, $delimiter, escape: '\\')) !== false) {
$line++;
if (count($row) !== $width) {
$badRows[] = $line;
}
}
fclose($handle);
if ($badRows !== []) {
throw new \RuntimeException('Rows with wrong column count: '.implode(', ', $badRows));
} Try / catch
try { foreach ($source as $row) { /* ... */ } } catch (\InvalidArgumentException $e) { if ($e->getMessage() === AbstractImporter::ERROR_CODE_COLUMNS_NUMBER) { $rowNum = $source->getCurrentRowNumber(); // report row number + skip/abort } else { throw $e; } } Prevention
- Always quote CSV values that contain the delimiter when generating exports.
- Reject or auto-fix ragged rows in a pre-pass instead of letting the iterator throw mid-import.
- Pin the delimiter to what the header actually uses; a mismatch makes every row fail the column count check.
- Surface getCurrentRowNumber() in import error reports so users can jump to the offending line.
When it happens
Trigger: Importing a CSV where a data row has more or fewer delimiters than the header (e.g. header with 5 columns, row with 6 because a value contains an unquoted comma); an Excel row with cells spilling past the header width; a trailing blank-but-delimited line like ',,,,' at end of file. Surfaces on the first current() call after next() reads the bad row.
Common situations: User-edited CSVs in Excel that re-save with different quoting; exports from other systems that pad or trim trailing columns; delimiter mismatch (file is semicolon-separated but ',' was passed, so fgetcsv splits into 1 column per row); hand-merged files with header rows repeated mid-file.
Related errors
- data_transfer::app.validation.errors.file-empty
- Unable to open file: '{$filePath}'
- data_transfer::app.validation.errors.file-empty
- Unable to open file: '{$filePath}'
- composer require failed
AI-assisted analysis of unopim/unopim@c27a402253 (2026-08-21).
Data as JSON: /api/errors/fb7e8ce2bacd275d.
Report an issue: GitHub.