PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
Trend(): Number of elements in coordinate arrays do not matc
Error message
Trend(): Number of elements in coordinate arrays do not match.
What it means
Thrown by Trend::trend() when non-empty X and Y arrays have different element counts. The method happily invents X values (range(1, n)) only when X is omitted entirely ($nX === 0); otherwise equal size is mandatory and a mismatch is rejected up front, before any cache key or regression class is built.
Source
Thrown at src/PhpSpreadsheet/Shared/Trend/Trend.php:68
/**
* @param mixed[] $yValues
* @param mixed[] $xValues
*/
public static function calculate(string $trendType = self::TREND_BEST_FIT, array $yValues = [], array $xValues = [], bool $const = true): BestFit
{
// Calculate number of points in each dataset
/** @var float[] $xValues */
$nY = count($yValues);
/** @var float[] $xValues */
$nX = count($xValues);
// Define X Values if necessary
if ($nX === 0) {
$xValues = range(1, $nY);
} elseif ($nY !== $nX) {
// Ensure both arrays of points are the same size
throw new SpreadsheetException('Trend(): Number of elements in coordinate arrays do not match.');
}
$key = md5($trendType . $const . serialize($yValues) . serialize($xValues));
// Determine which Trend method has been requested
switch ($trendType) {
// Instantiate and return the class for the requested Trend method
case self::TREND_LINEAR:
case self::TREND_LOGARITHMIC:
case self::TREND_EXPONENTIAL:
case self::TREND_POWER:
if (!isset(self::$trendCache[$key])) {
/** @var float[] $yValues */
$className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit';
/** @var float[] $xValues */
self::$trendCache[$key] = new $className($yValues, $xValues, $const);
}
return self::$trendCache[$key];View on GitHub (pinned to 65b080eef4)
Solutions
- Align the series before calling: ensure count($xValues) === count($yValues) (e.g. array_slice to the shorter, or rebuild both from one list of [x, y] pairs).
- Omit X entirely when it is just an index: Trend::trend($type, $yValues) generates 1..n automatically and cannot mismatch.
- If pairs may be ragged, normalize first: filter both arrays with the same predicate so entries drop in lockstep.
- Add a guard in your data-prep layer that throws a descriptive error naming both counts.
Example fix
// before
$fit = Trend::trend(Trend::TREND_LINEAR, $yValues, $xValues);
// Trend(): Number of elements in coordinate arrays do not match. (12 vs 11)
// after
assert(count($yValues) === count($xValues));
// rebuild both from shared pairs so they can't drift:
foreach ($points as ['x' => $x[], 'y' => $y[]]) {}
$fit = Trend::trend(Trend::TREND_LINEAR, $y, $x); Defensive patterns
Strategy: validation
Validate before calling
if (count($xValues) !== count($yValues)) {
$n = min(count($xValues), count($yValues));
$xValues = array_slice($xValues, 0, $n);
$yValues = array_slice($yValues, 0, $n); // or throw with both counts in the message
}
$fit = Trend::trend($type, $yValues, $xValues); Try / catch
try { $fit = Trend::trend($type, $yValues, $xValues); }
catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
if (str_contains($e->getMessage(), 'coordinate arrays do not match')) {
throw new InvalidArgumentException(sprintf(
'X/Y size mismatch (%d vs %d)', count($xValues), count($yValues)
), 0, $e);
}
throw $e;
} Prevention
- Build both series from one list of pairs so they cannot drift apart.
- Omit $xValues when it is just an index — Trend generates 1..n and skips the check.
- Apply the same filter predicate to both axes when dropping invalid points.
When it happens
Trigger: Trend::trend($trendType, $yValues, $xValues) with count($yValues) !== count($xValues), e.g. 12 monthly Y values against 11 X labels after an off-by-one slice, or X filtered while Y wasn't. Direct construction of BestFit subclasses (LinearBestFit etc.) performs the same check via parent::__construct($yValues, $xValues).
Common situations: Dataset assembled from separate queries/sources whose row counts drift; array_filter applied to one axis only; a trailing summary row appended to Y; nulls removed from one series but not the other.
Related errors
- Password exceeds 255 characters
- Polynomial Best Fit not yet implemented
- Unknown trend type {$trendType}
- Unsupported binary comparison operator
- Cloning the calculation engine is not allowed!
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/6cb4a178061e1f53.
Report an issue: GitHub.