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

  1. 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).
  2. Omit X entirely when it is just an index: Trend::trend($type, $yValues) generates 1..n automatically and cannot mismatch.
  3. If pairs may be ragged, normalize first: filter both arrays with the same predicate so entries drop in lockstep.
  4. 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

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


AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17). Data as JSON: /api/errors/6cb4a178061e1f53. Report an issue: GitHub.