trekhleb/javascript-algorithms · error · Error

The data is empty

Error message

The data is empty

What it means

KMeans(data, k) throws 'The data is empty' when the data argument is falsy (null, undefined or another falsy value) - the guard is !data, not a length check. An empty array [] actually passes this guard and instead crashes later at data[0].length, so this specific message means the dataset was never passed or is null. Cluster centers are seeded from the first k points, so k must not exceed the data size either.

Source

Thrown at src/algorithms/ml/k-means/kMeans.js:16

import * as mtrx from '../../math/matrix/Matrix';
import euclideanDistance from '../../math/euclidean-distance/euclideanDistance';

/**
 * Classifies the point in space based on k-Means algorithm.
 *
 * @param {number[][]} data - array of dataSet points, i.e. [[0, 1], [3, 4], [5, 7]]
 * @param {number} k - number of clusters
 * @return {number[]} - the class of the point
 */
export default function KMeans(
  data,
  k = 1,
) {
  if (!data) {
    throw new Error('The data is empty');
  }

  // Assign k clusters locations equal to the location of initial k points.
  const dataDim = data[0].length;
  const clusterCenters = data.slice(0, k);

  // Continue optimization till convergence.
  // Centroids should not be moving once optimized.
  // Calculate distance of each candidate vector from each cluster center.
  // Assign cluster number to each data vector according to minimum distance.

  // Matrix of distance from each data point to each cluster centroid.
  const distances = mtrx.zeros([data.length, k]);

  // Vector data points' classes. The value of -1 means that no class has bee assigned yet.
  const classes = Array(data.length).fill(-1);

  let iterate = true;

View on GitHub (pinned to 85293e3e2b)

Solutions

  1. Log data right before the call - it is null or undefined at call time; trace where it is assigned
  2. Default or short-circuit: const points = loadData() ?? []; then guard if (points.length === 0) return before calling KMeans
  3. If data arrives asynchronously, await it or run KMeans in the completion callback instead of synchronously
  4. Once non-null, also verify k <= data.length so seeding does not read past the array

Example fix

// before
import KMeans from './src/algorithms/ml/k-means/kMeans';
const clusters = KMeans(data, 3);
// data is undefined after a failed fetch -> throws

// after
const data = await fetchPoints();
if (!Array.isArray(data) || data.length === 0) {
  throw new Error('KMeans requires a non-empty array of points');
}
const clusters = KMeans(data, 3);
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(data) || data.length === 0 || !data.every(Array.isArray)) {
  throw new TypeError('KMeans expects a non-empty array of numeric points');
}
KMeans(data, k);

Type guard

const isPointSet = (d) => Array.isArray(d) && d.length > 0 && d.every(Array.isArray);

Try / catch

try {
  clusters = KMeans(data, k);
} catch (e) {
  if (e.message === 'The data is empty') {
    clusters = []; // no dataset: report or re-fetch
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: KMeans(null, 3); KMeans() with the argument missing entirely; a variable meant to hold parsed points that stayed undefined after a failed parse, an empty fetch, or an optional-chained config yielding undefined.

Common situations: Data fetched asynchronously and used before it arrives, JSON.parse returning null, upstream filtering reducing a dataset to nothing whose result is then passed on, or refactors renaming the data parameter.

Related errors


AI-assisted analysis of trekhleb/javascript-algorithms@85293e3e2b (2026-08-24). Data as JSON: /api/errors/82de65dfe4b01db6. Report an issue: GitHub.