{"record":{"id":"4b7bf0aa80598afc","repo":"remotion-dev/remotion","slug":"samples-must-be-1-but-got-samples","errorCode":null,"errorMessage":"\"samples\" must be >= 1, but got ${samples}","messagePattern":"\"samples\" must be >= 1, but got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/effects/src/light-trail/index.ts","lineNumber":133,"sourceCode":"};\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');\n\tassertOptionalFiniteNumber(params.decay, 'decay');\n\tassertOptionalFiniteNumber(params.threshold, 'threshold');\n\tassertOptionalFiniteNumber(params.samples, 'samples');\n\tassertOptionalColor(params.color, 'color');","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/light-trail/index.ts#L115-L151","documentation":"Thrown by @remotion/effects' lightTrail effect when the optional `samples` param resolves to a non-positive integer. After `?? DEFAULT_SAMPLES` (32), `validateSamples` first checks integer-ness, then rejects any value below 1. `samples` controls how many directional taps the trail shader uses to approximate the motion blur streak.","triggerScenarios":"Calling `lightTrail({samples: 0})`, `lightTrail({samples: -4})`, or passing a value that defaults/clamps to a non-positive number. Because the `??` coalescing only fills `undefined`, passing `0` explicitly bypasses the default and hits this guard. Non-integers (e.g. 0.5) are caught one branch earlier by a separate error.","commonSituations":"Animating `samples` from 0 upward and clamping to 0 at the tail of a spring; reading samples from a config that uses 0 as a sentinel for 'auto'; copying a value from another effect that allows 0 (e.g. blur radius) and reusing it here.","solutions":["Use `samples: Math.max(1, Math.round(value))` (or omit the prop to get the default 32) before passing it in.","If driving `samples` from an interpolated/integrated value, clamp the lower bound to 1 in the interpolation config.","Treat 0 or negative as 'unset' and conditionally spread the prop: `...(v > 0 ? {samples: v} : {})`.","Audit any shared config object reused across effects for a `samples` field that another effect permits as 0."],"exampleFix":"// before\nlightTrail({ samples: frame >= 10 ? samplesForFrame(frame) : 0 });\n\n// after\nconst raw = frame >= 10 ? samplesForFrame(frame) : 1;\nlightTrail({ samples: Math.max(1, Math.round(raw)) });","handlingStrategy":"validation","validationCode":"const safeSamples = (v: unknown): number => {\n  if (v === undefined || v === null) return 32; // DEFAULT_SAMPLES\n  if (typeof v !== 'number' || !Number.isFinite(v)) {\n    throw new TypeError('samples must be a finite number');\n  }\n  const n = Math.round(v);\n  if (n < 1) return 1;\n  return n;\n};\nlightTrail({ samples: safeSamples(userSamples) });","typeGuard":"const isSamples = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 64;","tryCatchPattern":null,"preventionTips":["Always coerce samples with Math.round and clamp to [1, 64] before passing it in.","Treat 0/negative as 'unset' and omit the prop rather than passing it.","Add a unit test that exercises the lower boundary at 1."],"tags":["validation","light-trail","effects","api-misuse"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}