{"record":{"id":"eae982ce23a4fbc8","repo":"mermaid-js/mermaid","slug":"could-not-find-a-suitable-point-for-the-given-dist","errorCode":null,"errorMessage":"Could not find a suitable point for the given distance","messagePattern":"Could not find a suitable point for the given distance","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mermaid/src/utils.ts","lineNumber":364,"sourceCode":"        // Calculate the coordinates\n        const distanceRatio = remainingDistance / vectorDistance;\n        if (distanceRatio <= 0) {\n          return prevPoint;\n        }\n        if (distanceRatio >= 1) {\n          return { x: point.x, y: point.y };\n        }\n        if (distanceRatio > 0 && distanceRatio < 1) {\n          return {\n            x: roundNumber((1 - distanceRatio) * prevPoint.x + distanceRatio * point.x, 5),\n            y: roundNumber((1 - distanceRatio) * prevPoint.y + distanceRatio * point.y, 5),\n          };\n        }\n      }\n    }\n    prevPoint = point;\n  }\n  throw new Error('Could not find a suitable point for the given distance');\n};\n\nconst calcCardinalityPosition = (\n  isRelationTypePresent: boolean,\n  points: Point[],\n  initialPosition: Point\n) => {\n  log.info(`our points ${JSON.stringify(points)}`);\n  if (points[0] !== initialPosition) {\n    points = points.reverse();\n  }\n  // Traverse only 25 total distance along points to find cardinality point\n  const distanceToCardinalityPoint = 25;\n  const center = calculatePoint(points, distanceToCardinalityPoint);\n  // if relation is present (Arrows will be added), change cardinality point off-set distance (d)\n  const d = isRelationTypePresent ? 10 : 5;\n  //Calculate Angle for x and y axis\n  const angle = Math.atan2(points[0].y - center.y, points[0].x - center.x);","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/mermaid-js/mermaid/blob/d93e9c88c01a599c062ee6a3f1462e3558ac6b90/packages/mermaid/src/utils.ts#L346-L382","documentation":"Thrown by calculatePoint when it cannot interpolate a point at the requested distance along the polyline. The loop walks consecutive point pairs subtracting segment lengths; if it never reaches the remaining distance (e.g. points has fewer than 2 entries so prevPoint is never set, or distanceToTraverse exceeds total path length), control falls through to this throw. It's reached from traverseEdge, calcCardinalityPosition, and calcTerminalLabelPosition.","triggerScenarios":"Calling calculatePoint with a single-point array (no segments → loop body never runs), with distanceToTraverse larger than the total polyline length, or with degenerate identical points whose total distance rounds to less than the target. The cardinality/terminal-label callers pass a fixed 25 (+markerSize) distance, so very short edges where total path < 25 can overshoot.","commonSituations":"A zero-length or self-loop edge whose points collapse to one coordinate, an edge between two identical node centers (overlapping nodes), or a diagram rendered before layout assigned positions (all points at origin). Also from custom edge routing that produces a single-point path.","solutions":["Ensure edges have at least two distinct points before calculating label/cardinality positions.","Confirm layout has run and assigned real coordinates (not all-zero origin) before edge post-processing.","Guard callers: if (points.length < 2) return points[0] before calling calculatePoint.","For very short edges, clamp distanceToTraverse to a fraction of total length rather than a fixed 25."],"exampleFix":"// before\ncalculatePoint([singlePoint], 25); // throws — no segment\n// after\nif (points.length < 2) return points[0];\nreturn calculatePoint(points, Math.min(25, totalLength));","handlingStrategy":"validation","validationCode":"function safeCalculatePoint(points: { x: number; y: number }[], dist: number) {\n  if (points.length < 2) return points[0];\n  let total = 0;\n  for (let i = 1; i < points.length; i++) total += Math.hypot(points[i].x - points[i-1].x, points[i].y - points[i-1].y);\n  return calculatePoint(points, Math.min(dist, total));\n}","typeGuard":"function hasEnoughPoints(pts: unknown[]): pts is { x: number; y: number }[] { return pts.length >= 2; }","tryCatchPattern":"try { return calculatePoint(points, dist); } catch (e) { if (/suitable point/.test(String(e))) { return points[0]; } throw e; }","preventionTips":["Ensure edges have ≥ 2 distinct points before label/cardinality math.","Run layout before edge post-processing so points have real coordinates.","Clamp fixed distances (25) to total path length."],"tags":["utils","geometry","edges","render"],"backgroundTag":null,"analyzedSha":"d93e9c88c01a599c062ee6a3f1462e3558ac6b90","analyzedAt":"2026-08-12T06:23:11.304Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}