{"record":{"id":"4230bca59f4b974d","repo":"remotion-dev/remotion","slug":"bezier-x-values-must-be-in-0-1-range","errorCode":null,"errorMessage":"bezier x values must be in [0, 1] range","messagePattern":"bezier x values must be in \\[0, 1\\] range","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/bezier.ts","lineNumber":96,"sourceCode":"\t\tif (currentSlope === 0.0) {\n\t\t\treturn aGuessT;\n\t\t}\n\n\t\tconst currentX = calcBezier(aGuessT, mX1, mX2) - aX;\n\t\taGuessT -= currentX / currentSlope;\n\t}\n\n\treturn aGuessT;\n}\n\nexport function bezier(\n\tmX1: number,\n\tmY1: number,\n\tmX2: number,\n\tmY2: number,\n): (x: number) => number {\n\tif (!(mX1 >= 0 && mX1 <= 1 && mX2 >= 0 && mX2 <= 1)) {\n\t\tthrow new Error('bezier x values must be in [0, 1] range');\n\t}\n\n\t// Precompute samples table\n\tconst sampleValues = float32ArraySupported\n\t\t? new Float32Array(kSplineTableSize)\n\t\t: new Array(kSplineTableSize);\n\tif (mX1 !== mY1 || mX2 !== mY2) {\n\t\tfor (let i = 0; i < kSplineTableSize; ++i) {\n\t\t\tsampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);\n\t\t}\n\t}\n\n\tfunction getTForX(aX: number): number {\n\t\tlet intervalStart = 0.0;\n\t\tlet currentSample = 1;\n\t\tconst lastSample = kSplineTableSize - 1;\n\n\t\tfor (","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/bezier.ts#L78-L114","documentation":"Remotion's bezier() builds a cubic-bezier easing function from four control points (x1,y1,x2,y2), matching CSS cubic-bezier semantics. For the curve to be a mathematically valid function (one y per x), the x control points must lie in [0,1]; the y points may take any value. The guard runs at curve construction and throws immediately on invalid x.","triggerScenarios":"Calling bezier(-0.1, 0, 1, 1), bezier(0, 0, 1.5, 1), or passing such values to Easing.bezier / interpolate's easing. Also triggered by dynamically computed control points that drift outside the unit interval due to rounding or bad math.","commonSituations":"Hand-tuning an easing curve and overshooting; copying a cubic-bezier from a design tool that allows extraneous x; computing control points from animation parameters without clamping.","solutions":["Clamp x control points to [0,1] before calling bezier: bezier(clamp(x1,0,1), y1, clamp(x2,0,1), y2).","Use a known-good preset (Easing.bezier(0.4, 0, 0.2, 1) etc.).","Validate the values at the source that produces the curve."],"exampleFix":"// before\nconst e = bezier(x1, 0, x2, 1); // x1 or x2 may be out of range\n\n// after\nconst e = bezier(\n  Math.min(1, Math.max(0, x1)), 0,\n  Math.min(1, Math.max(0, x2)), 1\n);","handlingStrategy":"validation","validationCode":"const clamp01 = (n: number): number => Math.min(1, Math.max(0, n));\nconst fn = bezier(clamp01(x1), y1, clamp01(x2), y2);","typeGuard":"const isValidBezierX = (x: number): boolean =>\n  typeof x === 'number' && Number.isFinite(x) && x >= 0 && x <= 1;","tryCatchPattern":null,"preventionTips":["Clamp x control points to [0,1] at the source that computes them.","Prefer Easing presets over hand-rolled curves.","Unit-test dynamic curve generators with edge values (0, 1, negatives)."],"tags":["animation","validation","easing","interpolate","math"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}