trekhleb/javascript-algorithms · error · Error

Vertex has already been added before

Error message

Vertex has already been added before

What it means

Graph.addVertex() stores vertices in this.vertices keyed by vertex.getKey(), and GraphVertex.getKey() returns the raw value (src/data-structures/graph/GraphVertex.js:118-120). The guard at Graph.js:18-20 rejects any vertex whose key already exists, enforcing one vertex per unique key. Because vertices live in a plain object, keys are string-coerced: values 1 and '1' collide.

Source

Thrown at src/data-structures/graph/Graph.js:19

export default class Graph {
  /**
   * @param {boolean} isDirected
   */
  constructor(isDirected = false) {
    this.vertices = {};
    this.edges = {};
    this.isDirected = isDirected;
  }

  /**
   * @param {GraphVertex} newVertex
   * @returns {Graph}
   */
  addVertex(newVertex) {
    const key = newVertex.getKey();

    if (this.vertices[key]) {
      throw new Error('Vertex has already been added before');
    }

    this.vertices[key] = newVertex;

    return this;
  }

  /**
   * @param {string} vertexKey
   * @returns GraphVertex
   */
  getVertexByKey(vertexKey) {
    return this.vertices[vertexKey];
  }

  /**
   * @param {GraphVertex} vertex
   * @returns {GraphVertex[]}

View on GitHub (pinned to 85293e3e2b)

Solutions

  1. Do not manually add vertices that already appear as edge endpoints - addEdge() registers them automatically; fetch them with getVertexByKey() when you need the stored instance.
  2. Check before inserting: if (!graph.getVertexByKey(vertex.getKey())) graph.addVertex(vertex);
  3. Deduplicate source data before building, e.g. const uniqueIds = [...new Set(rows.map((r) => r.id))];
  4. Normalize key types at the boundary (always String(id) or always Number(id)) so 1 and '1' cannot both occur.

Example fix

// before
graph.addEdge(new GraphEdge(a, b)); // auto-adds vertices a and b
graph.addVertex(a); // Error: Vertex has already been added before

// after
graph.addEdge(new GraphEdge(a, b));
if (!graph.getVertexByKey(a.getKey())) {
  graph.addVertex(a);
}
Defensive patterns

Strategy: validation

Validate before calling

const hasVertex = (graph, vertex) => Boolean(graph.getVertexByKey(vertex.getKey()));

if (!hasVertex(graph, vertex)) {
  graph.addVertex(vertex);
}

Try / catch

try {
  graph.addVertex(vertex);
} catch (error) {
  if (error.message === 'Vertex has already been added before') {
    vertex = graph.getVertexByKey(vertex.getKey()); // reuse the stored instance
  } else {
    throw error;
  }
}

Prevention

When it happens

Trigger: graph.addVertex(new GraphVertex('A')) called twice; addEdge(edge) first (it auto-registers both endpoint vertices at Graph.js:67-76) followed by a manual addVertex() of the same vertex - the addSameEdgeTwice path; two vertices whose values coerce to the same string key (1 vs '1').

Common situations: Building a graph from an edge list AND pre-adding vertices, so endpoints get inserted twice; ingesting rows with duplicate IDs; mixing numeric and string IDs coming from different sources (JSON payload vs query params).

Related errors


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