{"record":{"id":"94a9288343daa5cf","repo":"remotion-dev/remotion","slug":"endat-must-be-a-positive-number-instead-got-end","errorCode":null,"errorMessage":"endAt must be a positive number, instead got ${endAt}.","messagePattern":"endAt must be a positive number, instead got (.+?)\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/validate-start-from-props.ts","lineNumber":35,"sourceCode":"\t\t\tthrow new TypeError(\n\t\t\t\t`startFrom must be greater than equal to 0 instead got ${startFrom}.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tif (typeof endAt !== 'undefined') {\n\t\tif (typeof endAt !== 'number') {\n\t\t\tthrow new TypeError(\n\t\t\t\t`type of endAt prop must be a number, instead got type ${typeof endAt}.`,\n\t\t\t);\n\t\t}\n\n\t\tif (isNaN(endAt)) {\n\t\t\tthrow new TypeError('endAt prop can not be NaN.');\n\t\t}\n\n\t\tif (endAt <= 0) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`endAt must be a positive number, instead got ${endAt}.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tif ((endAt as number) < (startFrom as number)) {\n\t\tthrow new TypeError('endAt prop must be greater than startFrom prop.');\n\t}\n};\n\nexport const validateTrimProps = (\n\ttrimBefore: number | undefined,\n\ttrimAfter: number | undefined,\n) => {\n\tif (typeof trimBefore !== 'undefined') {\n\t\tif (typeof trimBefore !== 'number') {\n\t\t\tthrow new TypeError(\n\t\t\t\t`type of trimBefore prop must be a number, instead got type ${typeof trimBefore}.`,","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/validate-start-from-props.ts#L17-L53","documentation":"The deprecated endAt prop specifies the frame at which playback stops, and it must be strictly positive (greater than 0). validateStartFromProps rejects zero and negative values because an end frame of 0 or below would mean the media never plays.","triggerScenarios":"Passing endAt={0}, endAt={-5}, or a computed expression that evaluates to zero or a negative number.","commonSituations":"Setting endAt to 0 by mistake (e.g. defaulting an uninitialized variable to 0); subtracting a margin that drives the end before frame 0; off-by-one when endAt is computed from a duration that collapses to 0.","solutions":["Pass a positive frame number: endAt={200}.","Clamp the computed value to at least 1: endAt={Math.max(1, computed)}.","Verify the duration math that produces endAt; ensure the source media is long enough.","Migrate to the non-deprecated trimAfter prop (same positive constraint applies)."],"exampleFix":"// before\n<Video src={src} endAt={duration - margin} /> // can be <= 0\n// after\n<Video src={src} trimAfter={Math.max(1, duration - margin)} />","handlingStrategy":"validation","validationCode":"if (endAt !== undefined && endAt <= 0) {\n  throw new Error('endAt must be > 0');\n}","typeGuard":"const isValidEndAt = (v: unknown): v is number =>\n  typeof v === 'number' && !Number.isNaN(v) && v > 0;","tryCatchPattern":null,"preventionTips":["Clamp computed end frames with Math.max(1, value).","Default unset variables to undefined, not 0, so they are skipped rather than rejected.","Prefer trimAfter over the deprecated endAt."],"tags":["validation","props","deprecated","trimming","range"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}