trekhleb/javascript-algorithms · error · Error

One or two values are not in sets

Error message

One or two values are not in sets

What it means

Thrown by DisjointSet.union() when find() returns null for valueA or valueB (src/data-structures/disjoint-set/DisjointSet.js:54-59). find() builds a probe DisjointSetItem, derives its key via the constructor's keyCallback (or the raw value), and returns null when that key is absent from this.items - meaning the value was never registered with makeSet(). Union-find can only merge values that already belong to some set, so an unknown operand is treated as a programmer error rather than being silently auto-created.

Source

Thrown at src/data-structures/disjoint-set/DisjointSet.js:58

      return null;
    }

    return requiredDisjointItem.getRoot().getKey();
  }

  /**
   * Union by rank.
   *
   * @param {*} valueA
   * @param {*} valueB
   * @return {DisjointSet}
   */
  union(valueA, valueB) {
    const rootKeyA = this.find(valueA);
    const rootKeyB = this.find(valueB);

    if (rootKeyA === null || rootKeyB === null) {
      throw new Error('One or two values are not in sets');
    }

    if (rootKeyA === rootKeyB) {
      // In case if both elements are already in the same set then just return its key.
      return this;
    }

    const rootA = this.items[rootKeyA];
    const rootB = this.items[rootKeyB];

    if (rootA.getRank() < rootB.getRank()) {
      // If rootB's tree is bigger then make rootB to be a new root.
      rootB.addChild(rootA);

      return this;
    }

    // If rootA's tree is bigger then make rootA to be a new root.

View on GitHub (pinned to 85293e3e2b)

Solutions

  1. Bootstrap every value before merging: graph.getAllVertices().forEach((v) => ds.makeSet(v)); - this mirrors what kruskal() does internally.
  2. If values are objects, construct the set with a stable key callback: const ds = new DisjointSet((v) => v.id); and use the same value shape for makeSet() and union().
  3. Guard lazily when membership is uncertain: if (ds.find(a) === null) ds.makeSet(a); if (ds.find(b) === null) ds.makeSet(b); before ds.union(a, b).
  4. Verify you pass the identical value/reference to both makeSet() and union(); inspect Object.keys(ds.items) to see the registered keys.

Example fix

// before
const ds = new DisjointSet((v) => v.id);
ds.union(nodeA, nodeB); // Error: One or two values are not in sets

// after
const ds = new DisjointSet((v) => v.id);
graph.getAllVertices().forEach((vertex) => ds.makeSet(vertex));
ds.union(nodeA, nodeB);
Defensive patterns

Strategy: validation

Validate before calling

// find() returns null for values not in any set - cheap pre-check
const inSomeSet = (disjointSet, value) => disjointSet.find(value) !== null;

if (inSomeSet(ds, valueA) && inSomeSet(ds, valueB)) {
  ds.union(valueA, valueB);
} else {
  ds.makeSet(valueA); // or handle the unknown value explicitly
  ds.makeSet(valueB);
}

Try / catch

try {
  ds.union(valueA, valueB);
} catch (error) {
  if (error.message === 'One or two values are not in sets') {
    // One operand was never makeSet()-ed: register it or skip this pair.
  } else {
    throw error;
  }
}

Prevention

When it happens

Trigger: Calling ds.union(a, b) before ds.makeSet(a) and ds.makeSet(b) have both run. Concrete cases: a hand-written Kruskal loop that unions edge endpoints but never bootstraps makeSet() over all vertices; passing vertex.value to makeSet() but the GraphVertex object to union() (or vice versa) so the derived keys differ; a keyCallback that produces different key shapes at registration time and merge time.

Common situations: Reimplementing kruskal or detectUndirectedCycleUsingDisjointSet instead of using the shipped helpers (which do the makeSet bootstrap for you); refactoring vertex values from primitives to objects without adding a keyCallback; pipelines where a late-arriving node is merged before it is registered.

Related errors


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