{"record":{"id":"8914ac51fda7ae6b","repo":"remotion-dev/remotion","slug":"samples-must-be-an-integer-but-got-samples","errorCode":null,"errorMessage":"\"samples\" must be an integer, but got ${samples}","messagePattern":"\"samples\" must be an integer, but got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/effects/src/light-trail/index.ts","lineNumber":129,"sourceCode":"\treadonly decay: number;\n\treadonly threshold: number;\n\treadonly samples: number;\n\treadonly color: string;\n};\n\nconst resolve = (p: LightTrailParams): LightTrailResolved => ({\n\tdirection: p.direction ?? DEFAULT_DIRECTION,\n\tdistance: p.distance ?? DEFAULT_DISTANCE,\n\tintensity: p.intensity ?? DEFAULT_INTENSITY,\n\tdecay: p.decay ?? DEFAULT_DECAY,\n\tthreshold: p.threshold ?? DEFAULT_THRESHOLD,\n\tsamples: p.samples ?? DEFAULT_SAMPLES,\n\tcolor: p.color ?? DEFAULT_COLOR,\n});\n\nconst validateSamples = (samples: number): void => {\n\tif (!Number.isInteger(samples)) {\n\t\tthrow new TypeError(`\"samples\" must be an integer, but got ${samples}`);\n\t}\n\n\tif (samples < 1) {\n\t\tthrow new TypeError(`\"samples\" must be >= 1, but got ${samples}`);\n\t}\n\n\tif (samples > MAX_SAMPLES) {\n\t\tthrow new TypeError(\n\t\t\t`\"samples\" must be <= ${MAX_SAMPLES}, but got ${samples}`,\n\t\t);\n\t}\n};\n\nconst validateLightTrailParams = (params: LightTrailParams): void => {\n\tassertEffectParamsObject(params, 'Light trail');\n\tassertOptionalFiniteNumber(params.direction, 'direction');\n\tassertOptionalFiniteNumber(params.distance, 'distance');\n\tassertOptionalFiniteNumber(params.intensity, 'intensity');","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/light-trail/index.ts#L111-L147","documentation":"Thrown by the `lightTrail()` effect's `validateSamples()` when the resolved `samples` value is not an integer. `samples` controls the number of trail accumulation passes in the GLSL loop (declared as `int` with a compile-time `MAX_SAMPLES = 64`), so fractional values are meaningless and rejected with a TypeError before reaching the GPU.","triggerScenarios":"Passing `lightTrail({samples: 32.5})`, a fractional result of division (e.g. `maxSamples / 2` when maxSamples is odd), or animating `samples` with an interpolate whose easing produces fractional output.","commonSituations":"Slider with a non-integer step; computed sample counts from arithmetic; rounding mistakes where the user assumed the library would floor the value.","solutions":["Pass an integer `samples` between 1 and 64 (default 32).","Wrap computed values with `Math.round()` before passing them in.","If animating, round the interpolated output or animate in integer steps."],"exampleFix":"// before\nlightTrail({samples: total / 3})\n\n// after\nlightTrail({samples: Math.round(total / 3)})","handlingStrategy":"validation","validationCode":"if (typeof params.samples === 'number' && !Number.isInteger(params.samples)) {\n  params = {...params, samples: Math.round(params.samples)};\n}","typeGuard":"const isSamplesSafe = (s: number | undefined): boolean =>\n  s === undefined || (Number.isInteger(s) && s >= 1 && s <= 64);","tryCatchPattern":null,"preventionTips":["Always Math.round() computed sample counts before passing them in.","Set slider steps to 1 so fractional samples can't be selected.","When animating samples, round the interpolated value or use integer keyframes."],"tags":["light-trail","validation","samples","effect-params","webgl2"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}