{"record":{"id":"ac8358f47d00bcad","repo":"toeverything/AFFiNE","slug":"a-curve-must-have-at-least-three-points","errorCode":null,"errorMessage":"A curve must have at least three points.","messagePattern":"A curve must have at least three points\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"blocksuite/affine/blocks/surface/src/utils/points-on-curve/curve-to-bezier.ts","lineNumber":13,"sourceCode":"import type { Point } from '../rough/geometry.js';\n\nfunction clone(p: Point): Point {\n  return [...p] as Point;\n}\n\nexport function curveToBezier(\n  pointsIn: readonly Point[],\n  curveTightness = 0\n): Point[] {\n  const len = pointsIn.length;\n  if (len < 3) {\n    throw new Error('A curve must have at least three points.');\n  }\n  const out: Point[] = [];\n  if (len === 3) {\n    out.push(\n      clone(pointsIn[0]),\n      clone(pointsIn[1]),\n      clone(pointsIn[2]),\n      clone(pointsIn[2])\n    );\n  } else {\n    const points: Point[] = [];\n    points.push(pointsIn[0], pointsIn[0]);\n    for (let i = 1; i < pointsIn.length; i++) {\n      points.push(pointsIn[i]);\n      if (i === pointsIn.length - 1) {\n        points.push(pointsIn[i]);\n      }\n    }","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/blocksuite/affine/blocks/surface/src/utils/points-on-curve/curve-to-bezier.ts#L1-L31","documentation":"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.","triggerScenarios":"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.","commonSituations":"A drawing/pen input event captured too few pointer samples; degenerate shapes where vertices collapsed; filtering that removed too many points before curve conversion.","solutions":["Guard the caller: only invoke curveToBezier when pointsIn.length >= 3.","If you must handle short inputs, pad by duplicating the last point to reach 3, or fall back to a straight line.","Investigate why the upstream point source is under-supplying points."],"exampleFix":"// before\ncurveToBezier([[0,0],[1,1]]); // throws\n\n// after\nif (points.length < 3) return getDirectPath(points[0], points[points.length-1]);\ncurveToBezier(points);","handlingStrategy":"validation","validationCode":"function toBezierSafe(points: readonly number[][]) {\n  return points.length >= 3 ? curveToBezier(points) : [points[0], points[points.length-1]];\n}","typeGuard":"const hasMinPoints = (pts: readonly unknown[]): pts is number[] => Array.isArray(pts) && pts.length >= 3;","tryCatchPattern":null,"preventionTips":["Check points.length >= 3 before calling curveToBezier","Sample enough pointer points before attempting curve fitting"],"tags":["curve","geometry","points","bezier"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}