{"record":{"id":"4237de8f3b42f3e5","repo":"mermaid-js/mermaid","slug":"commit-positions-not-found-for-commits-commita-i","errorCode":null,"errorMessage":"Commit positions not found for commits ${commitA.id} and ${commitB.id}","messagePattern":"Commit positions not found for commits (.+?) and (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mermaid/src/diagrams/git/gitGraphRenderer.ts","lineNumber":664,"sourceCode":"    lanes.push(candidate);\n    return candidate;\n  }\n  const diff = Math.abs(y1 - y2);\n  return findLane(y1, y2 - diff / 5, depth + 1);\n};\n\nconst drawArrow = (\n  svg: d3.Selection<SVGGElement, unknown, HTMLElement, any>,\n  commitA: Commit,\n  commitB: Commit,\n  allCommits: Map<string, Commit>\n) => {\n  const { theme: arrowTheme } = getConfig();\n  const useColorTheme = COLOR_THEMES.has(arrowTheme ?? '');\n  const p1 = commitPos.get(commitA.id); // arrowStart\n  const p2 = commitPos.get(commitB.id); // arrowEnd\n  if (p1 === undefined || p2 === undefined) {\n    throw new Error(`Commit positions not found for commits ${commitA.id} and ${commitB.id}`);\n  }\n  const arrowNeedsRerouting = shouldRerouteArrow(commitA, commitB, p1, p2, allCommits);\n  // log.debug('drawArrow', p1, p2, arrowNeedsRerouting, commitA.id, commitB.id);\n\n  // Lower-right quadrant logic; top-left is 0,0\n\n  let arc = '';\n  let arc2 = '';\n  let radius = 0;\n  let offset = 0;\n\n  let colorClassNum = branchPos.get(commitB.branch)?.index;\n  if (commitB.type === commitType.MERGE && commitA.id !== commitB.parents[0]) {\n    colorClassNum = branchPos.get(commitA.branch)?.index;\n  }\n\n  let lineDef;\n  if (arrowNeedsRerouting) {","sourceCodeStart":646,"sourceCodeEnd":682,"githubUrl":"https://github.com/mermaid-js/mermaid/blob/d93e9c88c01a599c062ee6a3f1462e3558ac6b90/packages/mermaid/src/diagrams/git/gitGraphRenderer.ts#L646-L682","documentation":"Thrown by drawArrow in the gitGraph renderer when commitPos.get() returns undefined for either the source (commitA) or destination (commitB) commit. commitPos is a Map populated during the commit layout pass (drawCommits); an arrow references a commit id that was never positioned because it was never drawn or registered. This indicates a broken commit graph: a parent/child relationship points at a commit id the layout phase never processed.","triggerScenarios":"Calling mermaid.render() on a gitGraph diagram where a commit is referenced as a parent (e.g. in a merge or branch statement) but was never declared with a commit statement; or a commit id typo makes the arrow target a non-existent id; or parallel-commits mode produces a commit that the layout loop skipped.","commonSituations":"Typo in commit ids between 'commit id:\"A\"' and 'merge A'; declaring branches/merges before the referenced commits exist; upgrading mermaid versions where the gitGraph grammar changed and a previously-valid diagram now leaves commits unprocessed; internal bugs in parallel commit layout.","solutions":["Open the diagram source and verify every commit id referenced in branch/merge/commit lines is declared exactly once with a matching id.","Simplify the gitGraph to a linear history first, then re-add branches/merges one at a time to isolate the offending reference.","Check mermaid changelog for gitGraph grammar changes if this appeared after a version bump.","File an issue at the mermaid repo if the diagram is valid but still throws — include the minimal reproducing diagram text."],"exampleFix":"// before\ngitGraph\n  commit id:\"A\"\n  branch dev\n  commit id:\"B\"\n  merge maintypo   // typo: 'maintypo' is not a declared branch/commit\n\n// after\ngitGraph\n  commit id:\"A\"\n  branch dev\n  commit id:\"B\"\n  merge main        // correct branch name","handlingStrategy":"validation","validationCode":"// Before rendering, verify every commit referenced in branches/merges exists.\n// Pseudocode over the parsed gitGraph db:\nconst declared = new Set(db.getCommits().keys());\nfor (const [id, commit] of db.getCommits()) {\n  for (const parentId of commit.parents ?? []) {\n    if (!declared.has(parentId)) {\n      throw new Error(`Commit ${id} references unknown parent ${parentId}`);\n    }\n  }\n}","typeGuard":"function commitExists(db, id: string): id is string {\n  return db.getCommits().has(id);\n}","tryCatchPattern":"try {\n  await mermaid.render('g', diagramText);\n} catch (e) {\n  if (e instanceof Error && /Commit positions not found/.test(e.message)) {\n    // surface a user-facing message about a dangling commit reference\n    showUserError('Your gitGraph references a commit that was never declared. Check commit ids in branch/merge lines.');\n  } else {\n    throw e;\n  }\n}","preventionTips":["Declare every commit with a unique explicit id before referencing it in branch/merge lines.","Use the mermaid Live Editor to validate gitGraph text before embedding it.","Add a CI step that runs mermaid.parse() on diagram sources to catch dangling references early."],"tags":["mermaid","gitgraph","rendering","data-integrity"],"backgroundTag":null,"analyzedSha":"d93e9c88c01a599c062ee6a3f1462e3558ac6b90","analyzedAt":"2026-08-12T06:23:11.304Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}