{"record":{"id":"fbdf4b3c156c15f7","repo":"trekhleb/javascript-algorithms","slug":"vertex-has-already-been-added-before","errorCode":null,"errorMessage":"Vertex has already been added before","messagePattern":"Vertex has already been added before","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/data-structures/graph/Graph.js","lineNumber":19,"sourceCode":"export default class Graph {\n  /**\n   * @param {boolean} isDirected\n   */\n  constructor(isDirected = false) {\n    this.vertices = {};\n    this.edges = {};\n    this.isDirected = isDirected;\n  }\n\n  /**\n   * @param {GraphVertex} newVertex\n   * @returns {Graph}\n   */\n  addVertex(newVertex) {\n    const key = newVertex.getKey();\n\n    if (this.vertices[key]) {\n      throw new Error('Vertex has already been added before');\n    }\n\n    this.vertices[key] = newVertex;\n\n    return this;\n  }\n\n  /**\n   * @param {string} vertexKey\n   * @returns GraphVertex\n   */\n  getVertexByKey(vertexKey) {\n    return this.vertices[vertexKey];\n  }\n\n  /**\n   * @param {GraphVertex} vertex\n   * @returns {GraphVertex[]}","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/trekhleb/javascript-algorithms/blob/85293e3e2b88f4d2ce330d956b139cf628aa1e82/src/data-structures/graph/Graph.js#L1-L37","documentation":"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.","triggerScenarios":"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').","commonSituations":"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).","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."],"exampleFix":"// before\ngraph.addEdge(new GraphEdge(a, b)); // auto-adds vertices a and b\ngraph.addVertex(a); // Error: Vertex has already been added before\n\n// after\ngraph.addEdge(new GraphEdge(a, b));\nif (!graph.getVertexByKey(a.getKey())) {\n  graph.addVertex(a);\n}","handlingStrategy":"validation","validationCode":"const hasVertex = (graph, vertex) => Boolean(graph.getVertexByKey(vertex.getKey()));\n\nif (!hasVertex(graph, vertex)) {\n  graph.addVertex(vertex);\n}","typeGuard":null,"tryCatchPattern":"try {\n  graph.addVertex(vertex);\n} catch (error) {\n  if (error.message === 'Vertex has already been added before') {\n    vertex = graph.getVertexByKey(vertex.getKey()); // reuse the stored instance\n  } else {\n    throw error;\n  }\n}","preventionTips":["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."],"tags":["graph","duplicate-vertex","unique-key","add-vertex"],"backgroundTag":"duplicate-key-insertion","analyzedSha":"85293e3e2b88f4d2ce330d956b139cf628aa1e82","analyzedAt":"2026-08-24T05:59:10.417Z","schemaVersion":2},"datasetVersion":"2026-08-24T07:17:09.176Z"}