toeverything/AFFiNE · error · Error

A curve must have at least three points.

Error message

A curve must have at least three points.

What it means

curveToBezier() converts a polyline of points into a cubic bezier curve representation. It requires at least 3 points to form a curve, so len < 3 throws immediately. This mirrors the mathematical minimum for defining a quadratic curve segment.

Source

Thrown at blocksuite/affine/blocks/surface/src/utils/points-on-curve/curve-to-bezier.ts:13

import type { Point } from '../rough/geometry.js';

function clone(p: Point): Point {
  return [...p] as Point;
}

export function curveToBezier(
  pointsIn: readonly Point[],
  curveTightness = 0
): Point[] {
  const len = pointsIn.length;
  if (len < 3) {
    throw new Error('A curve must have at least three points.');
  }
  const out: Point[] = [];
  if (len === 3) {
    out.push(
      clone(pointsIn[0]),
      clone(pointsIn[1]),
      clone(pointsIn[2]),
      clone(pointsIn[2])
    );
  } else {
    const points: Point[] = [];
    points.push(pointsIn[0], pointsIn[0]);
    for (let i = 1; i < pointsIn.length; i++) {
      points.push(pointsIn[i]);
      if (i === pointsIn.length - 1) {
        points.push(pointsIn[i]);
      }
    }

View on GitHub (pinned to 26c515e050)

Solutions

  1. Guard the caller: only invoke curveToBezier when pointsIn.length >= 3.
  2. If you must handle short inputs, pad by duplicating the last point to reach 3, or fall back to a straight line.
  3. Investigate why the upstream point source is under-supplying points.

Example fix

// before
curveToBezier([[0,0],[1,1]]); // throws

// after
if (points.length < 3) return getDirectPath(points[0], points[points.length-1]);
curveToBezier(points);
Defensive patterns

Strategy: validation

Validate before calling

function toBezierSafe(points: readonly number[][]) {
  return points.length >= 3 ? curveToBezier(points) : [points[0], points[points.length-1]];
}

Type guard

const hasMinPoints = (pts: readonly unknown[]): pts is number[] => Array.isArray(pts) && pts.length >= 3;

Prevention

When it happens

Trigger: Calling curveToBezier(points) with a pointsIn array of length 0, 1, or 2. Common when downstream geometry (e.g. a freehand stroke) produced too few sampled points.

Common situations: A drawing/pen input event captured too few pointer samples; degenerate shapes where vertices collapsed; filtering that removed too many points before curve conversion.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/ac8358f47d00bcad. Report an issue: GitHub.