{"record":{"id":"82de65dfe4b01db6","repo":"trekhleb/javascript-algorithms","slug":"the-data-is-empty","errorCode":null,"errorMessage":"The data is empty","messagePattern":"The data is empty","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/algorithms/ml/k-means/kMeans.js","lineNumber":16,"sourceCode":"import * as mtrx from '../../math/matrix/Matrix';\nimport euclideanDistance from '../../math/euclidean-distance/euclideanDistance';\n\n/**\n * Classifies the point in space based on k-Means algorithm.\n *\n * @param {number[][]} data - array of dataSet points, i.e. [[0, 1], [3, 4], [5, 7]]\n * @param {number} k - number of clusters\n * @return {number[]} - the class of the point\n */\nexport default function KMeans(\n  data,\n  k = 1,\n) {\n  if (!data) {\n    throw new Error('The data is empty');\n  }\n\n  // Assign k clusters locations equal to the location of initial k points.\n  const dataDim = data[0].length;\n  const clusterCenters = data.slice(0, k);\n\n  // Continue optimization till convergence.\n  // Centroids should not be moving once optimized.\n  // Calculate distance of each candidate vector from each cluster center.\n  // Assign cluster number to each data vector according to minimum distance.\n\n  // Matrix of distance from each data point to each cluster centroid.\n  const distances = mtrx.zeros([data.length, k]);\n\n  // Vector data points' classes. The value of -1 means that no class has bee assigned yet.\n  const classes = Array(data.length).fill(-1);\n\n  let iterate = true;","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/trekhleb/javascript-algorithms/blob/85293e3e2b88f4d2ce330d956b139cf628aa1e82/src/algorithms/ml/k-means/kMeans.js#L1-L34","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Log data right before the call - it is null or undefined at call time; trace where it is assigned","Default or short-circuit: const points = loadData() ?? []; then guard if (points.length === 0) return before calling KMeans","If data arrives asynchronously, await it or run KMeans in the completion callback instead of synchronously","Once non-null, also verify k <= data.length so seeding does not read past the array"],"exampleFix":"// before\nimport KMeans from './src/algorithms/ml/k-means/kMeans';\nconst clusters = KMeans(data, 3);\n// data is undefined after a failed fetch -> throws\n\n// after\nconst data = await fetchPoints();\nif (!Array.isArray(data) || data.length === 0) {\n  throw new Error('KMeans requires a non-empty array of points');\n}\nconst clusters = KMeans(data, 3);","handlingStrategy":"validation","validationCode":"if (!Array.isArray(data) || data.length === 0 || !data.every(Array.isArray)) {\n  throw new TypeError('KMeans expects a non-empty array of numeric points');\n}\nKMeans(data, k);","typeGuard":"const isPointSet = (d) => Array.isArray(d) && d.length > 0 && d.every(Array.isArray);","tryCatchPattern":"try {\n  clusters = KMeans(data, k);\n} catch (e) {\n  if (e.message === 'The data is empty') {\n    clusters = []; // no dataset: report or re-fetch\n  } else {\n    throw e;\n  }\n}","preventionTips":["Validate loaded data at the boundary (fetch/parse), not at the ML call site","Never pass possibly-async values straight into numeric algorithms","Remember [] passes this guard and fails later - also check length"],"tags":["machine-learning","k-means","clustering","null-check","validation"],"backgroundTag":"null-or-undefined-argument","analyzedSha":"85293e3e2b88f4d2ce330d956b139cf628aa1e82","analyzedAt":"2026-08-24T05:59:10.417Z","schemaVersion":2},"datasetVersion":"2026-08-24T07:17:09.176Z"}