TheAlgorithms/JavaScript · error · Error

key has to be a function or else left undefined

Error message

key has to be a function or else left undefined

What it means

Thrown by the UnionFind constructor when an optional key argument is supplied but is not a function. The key is used internally to map caller indices to internal indices (key = key || function(a){return a}), so a non-function key would break every subsequent find/union call. Only undefined/omitted triggers the default; any other truthy non-function type is rejected.

Source

Thrown at Search/UnionFind.js:20

 * union find data structure for javascript
 *
 * In computer science, a disjoint-set data structure, also called a union–find data structure or merge–find set,
 * is a data structure that stores a collection of disjoint (non-overlapping) sets. Equivalently, it stores a partition
 * of a set into disjoint subsets. It provides operations for adding new sets, merging sets (replacing them by their union),
 * and finding a representative member of a set.
 * The last operation allows to find out efficiently if any two elements are in the same or different sets.
 *
 * Disjoint-set data structures play a key role in Kruskal's algorithm for finding the minimum spanning tree of a graph.
 * The importance of minimum spanning trees means that disjoint-set data structures underlie a wide variety of algorithms.
 * In addition, disjoint-set data structures also have applications to symbolic computation, as well in compilers,
 * especially for register allocation problems.
 *
 * you can learn more on disjoint-set / union–find data structure at https://en.wikipedia.org/wiki/Disjoint-set_data_structure
 */
function UnionFind(n, key) {
  if (!(this instanceof UnionFind)) return new UnionFind(n)
  if (key && typeof key !== 'function') {
    throw new Error('key has to be a function or else left undefined')
  }
  let cnt, length
  // init Union Find with number of distinct groups. Each group will be referred to as index of the array of size 'size' starting at 0.
  // Provide an optional key function that maps these indices. I.e., for the groups starting with 1 provide function(a){return a-1;}. The default value is function(a){return a;}.
  key =
    key ||
    function (a) {
      return a
    }
  cnt = length = n
  const id = new Array(n)
  const sz = new Array(n)
  for (let i = 0; i < n; i++) {
    id[i] = i
    sz[i] = 1
  }
  // Returns the number of elements of uf object.
  this.size = function () {

View on GitHub (pinned to 5c39e87a9a)

Solutions

  1. Omit the second argument entirely to use the identity mapping.
  2. Pass an actual function, e.g. new UnionFind(n, (a) => a - 1) for 1-based indices.
  3. Pass null or undefined (not some other falsy placeholder) to take the default.

Example fix

// before
const uf = new UnionFind(n, 'id')

// after
const uf = new UnionFind(n, (a) => a - 1) // 1-based to 0-based mapping
Defensive patterns

Strategy: type-guard

Validate before calling

function safeUnionFind(n, key) {
  if (key !== undefined && typeof key !== 'function') {
    throw new TypeError('key must be a function or undefined')
  }
  return new UnionFind(n, key)
}

Type guard

function isOptionalFunction(k) {
  return k === undefined || k === null || typeof k === 'function'
}

Try / catch

try {
  new UnionFind(n, key)
} catch (e) {
  if (e.message.includes('key has to be a function')) {
    new UnionFind(n) // retry with default identity key
  } else throw e
}

Prevention

When it happens

Trigger: Calling new UnionFind(n, 'id'), new UnionFind(n, 5), new UnionFind(n, {map: fn}), or new UnionFind(n, true). Passing null does NOT throw (it is falsy, so the default function is used).

Common situations: Passing a key string instead of an accessor function; passing an object whose property is the function but forgetting to extract it; copy-paste from an API that expects a string mapper.

Related errors


AI-assisted analysis of TheAlgorithms/JavaScript@5c39e87a9a (2026-08-13). Data as JSON: /api/errors/f215fc391bb61461. Report an issue: GitHub.