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
- 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.
- Check before inserting: if (!graph.getVertexByKey(vertex.getKey())) graph.addVertex(vertex);
- Deduplicate source data before building, e.g. const uniqueIds = [...new Set(rows.map((r) => r.id))];
- 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
- Pick one insertion path per vertex: addVertex() up front OR let addEdge() auto-register endpoints - not both.
- Deduplicate input rows/IDs before constructing the graph.
- Normalize IDs to one primitive type before they become vertex values (object keys stringify, so 1 and '1' collide).
- Reuse the stored instance via getVertexByKey() instead of re-adding it.
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.