toeverything/AFFiNE · error
A curve must have at least three points.
Error message
A curve must have at least three points.
What it means
After enum handling, the validator compares the runtime type of the value (via inputType — objects/arrays/null become 'json') with the schema-declared field type; a mismatch throws with both the expected and received type names. undefined values are dropped earlier and null is only allowed for optional fields, so this fires on present, non-null values of the wrong JS type.
Solutions
- Coerce the value to the declared type before writing (Number(id), String(x))
- Fix the schema declaration if it was wrong (e.g. the field genuinely holds string ids, declare type: 'string')
- Validate at the boundary: a small typeof-per-schema-field check before the write gives a clearer stack
Example fix
// before
table.insert({ data: { id: 'a1', count: '42' } }); // schema: count is 'number'
// after
table.insert({ data: { id: 'a1', count: 42 } });
// or coerce at the boundary: { ...dto, count: Number(dto.count) } Defensive patterns
Strategy: type-guard
Validate before calling
null
Type guard
function matchesFieldType(value: unknown, type: FieldType): boolean {
const actual =
value === null || Array.isArray(value) || typeof value === 'object' ? 'json' : typeof value;
return actual === type;
}
// before writing:
for (const [key, field] of Object.entries(table.schema)) {
if (data[key] !== undefined && data[key] !== null && !matchesFieldType(data[key], field.type)) {
throw new Error(`${key}: expected ${field.type}, got ${typeof data[key]}`);
}
} Prevention
- Coerce at the boundary: Number() for numeric fields, String() for text arriving from URL params or forms
- Keep schema type declarations in sync with the runtime types the writing layer actually produces
- Remember objects/arrays/null are treated as 'json' — declare such fields type: 'json', not 'string'
When it happens
Trigger: Inserting a string into a field declared type: 'number' (id: '123' from a URL param); booleans into 'string' fields; Date objects into 'string' fields; arrays/objects into scalar fields while the schema says 'string' rather than 'json'.
Common situations: URL/query params and form inputs yielding strings; JSON round-trips losing number types; schema types written to match one layer while another layer produces different runtime types.
Related errors
- Bad segment
- Path data ended short
- ValueNotExists
- Param not a number
- [Table( )]: Field ' ' type mismatch. Expected type ' ' but…
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/ac8358f47d00bcad.
Report an issue: GitHub.
Appendix: 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 b4c8548c09)