mermaid-js/mermaid · error · Error

Could not find a suitable point for the given distance

Error message

Could not find a suitable point for the given distance

What it means

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.

Solutions

  1. Ensure edges have at least two distinct points before calculating label/cardinality positions.
  2. Confirm layout has run and assigned real coordinates (not all-zero origin) before edge post-processing.
  3. Guard callers: if (points.length < 2) return points[0] before calling calculatePoint.
  4. For very short edges, clamp distanceToTraverse to a fraction of total length rather than a fixed 25.

Example fix

// before
calculatePoint([singlePoint], 25); // throws — no segment
// after
if (points.length < 2) return points[0];
return calculatePoint(points, Math.min(25, totalLength));
Defensive patterns

Strategy: validation

Validate before calling

function safeCalculatePoint(points: { x: number; y: number }[], dist: number) {
  if (points.length < 2) return points[0];
  let total = 0;
  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);
  return calculatePoint(points, Math.min(dist, total));
}

Type guard

function hasEnoughPoints(pts: unknown[]): pts is { x: number; y: number }[] { return pts.length >= 2; }

Try / catch

try { return calculatePoint(points, dist); } catch (e) { if (/suitable point/.test(String(e))) { return points[0]; } throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mermaid-js/mermaid@d93e9c88c0 (2026-08-12). Data as JSON: /api/errors/eae982ce23a4fbc8. Report an issue: GitHub.

Appendix: source

Thrown at packages/mermaid/src/utils.ts:364

        // Calculate the coordinates
        const distanceRatio = remainingDistance / vectorDistance;
        if (distanceRatio <= 0) {
          return prevPoint;
        }
        if (distanceRatio >= 1) {
          return { x: point.x, y: point.y };
        }
        if (distanceRatio > 0 && distanceRatio < 1) {
          return {
            x: roundNumber((1 - distanceRatio) * prevPoint.x + distanceRatio * point.x, 5),
            y: roundNumber((1 - distanceRatio) * prevPoint.y + distanceRatio * point.y, 5),
          };
        }
      }
    }
    prevPoint = point;
  }
  throw new Error('Could not find a suitable point for the given distance');
};

const calcCardinalityPosition = (
  isRelationTypePresent: boolean,
  points: Point[],
  initialPosition: Point
) => {
  log.info(`our points ${JSON.stringify(points)}`);
  if (points[0] !== initialPosition) {
    points = points.reverse();
  }
  // Traverse only 25 total distance along points to find cardinality point
  const distanceToCardinalityPoint = 25;
  const center = calculatePoint(points, distanceToCardinalityPoint);
  // if relation is present (Arrows will be added), change cardinality point off-set distance (d)
  const d = isRelationTypePresent ? 10 : 5;
  //Calculate Angle for x and y axis
  const angle = Math.atan2(points[0].y - center.y, points[0].x - center.x);

View on GitHub (pinned to d93e9c88c0)