{"record":{"id":"2e2c0f3d139ed194","repo":"remotion-dev/remotion","slug":"name-must-be-a-number-number-tuple-2e2c0f","errorCode":null,"errorMessage":"\"${name}\" must be a [number, number] tuple","messagePattern":"\"(.+?)\" must be a \\[number, number\\] tuple","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/effects/src/zoom-blur/index.ts","lineNumber":83,"sourceCode":"};\n\nconst resolve = (params: ZoomBlurParams): ZoomBlurResolved => ({\n\tamount: params.amount ?? DEFAULT_AMOUNT,\n\tcenter: [...(params.center ?? DEFAULT_CENTER)] as ZoomBlurCenter,\n\tsamples: params.samples ?? DEFAULT_SAMPLES,\n});\n\nconst assertOptionalUvCoordinate = (value: unknown, name: string): void => {\n\tif (value === undefined) {\n\t\treturn;\n\t}\n\n\tif (\n\t\t!Array.isArray(value) ||\n\t\tvalue.length !== 2 ||\n\t\tvalue.some((item) => typeof item !== 'number' || !Number.isFinite(item))\n\t) {\n\t\tthrow new TypeError(`\"${name}\" must be a [number, number] tuple`);\n\t}\n};\n\nconst assertOptionalInteger = (value: unknown, name: string): void => {\n\tif (value === undefined) {\n\t\treturn;\n\t}\n\n\tif (!Number.isInteger(value)) {\n\t\tthrow new TypeError(\n\t\t\t`\"${name}\" must be an integer, but got ${JSON.stringify(value)}`,\n\t\t);\n\t}\n};\n\nconst validateZoomBlurParams = (params: ZoomBlurParams): void => {\n\tassertEffectParamsObject(params, 'Zoom Blur');\n\tassertOptionalFiniteNumber(params.amount, 'amount');","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/zoom-blur/index.ts#L65-L101","documentation":"The zoomBlur effect validates its optional `center` parameter, which must be a two-element array of finite numbers representing UV coordinates. If `center` is provided but is not exactly a `[number, number]` tuple (e.g., has 3 elements, contains a string, includes NaN/Infinity, or is a non-array value), this TypeError is thrown before any WebGL work begins. The check runs during `validateParams` which is invoked by the effect framework when the effect is set up or applied.","triggerScenarios":"Passing `center` as `[[0.5, 0.5]]` (nested array), `[0.5]` (single element), `[0.5, 0.5, 0.5]` (three elements), `['0.5', '0.5']` (strings), `[NaN, 0.5]`, `[Infinity, 0.5]`, or a plain object `{x: 0.5, y: 0.5}` to `zoomBlur({center: ...})`.","commonSituations":"Deserialization from JSON that produces different array shapes, UI slider components emitting objects instead of arrays, spreading a nested structure accidentally, or passing pixel coordinates instead of normalized 0–1 UV coordinates.","solutions":["Ensure `center` is a flat two-element array of finite numbers, e.g. `center: [0.5, 0.5]`.","If omitting `center`, remove the key entirely so the default `[0.5, 0.5]` applies.","If your source data uses objects, map to an array before passing: `center: [data.x, data.y]`."],"exampleFix":"// before\nzoomBlur({ center: { x: 0.5, y: 0.5 } });\n\n// after\nzoomBlur({ center: [0.5, 0.5] });","handlingStrategy":"type-guard","validationCode":"const isNumberTuple = (v: unknown): v is [number, number] =>\n  Array.isArray(v) && v.length === 2 && v.every((n) => typeof n === 'number' && Number.isFinite(n));\n\nif (center !== undefined && !isNumberTuple(center)) {\n  // use default or throw a custom error\n}","typeGuard":"const isUvCoordinate = (v: unknown): v is readonly [number, number] =>\n  Array.isArray(v) &&\n  v.length === 2 &&\n  typeof v[0] === 'number' && Number.isFinite(v[0]) &&\n  typeof v[1] === 'number' && Number.isFinite(v[1]);","tryCatchPattern":null,"preventionTips":["Always pass center as a literal two-element array of numbers.","Validate deserialized data with a type guard before passing to zoomBlur.","Use TypeScript's readonly tuple type to get compile-time checking."],"tags":["validation","effects","zoom-blur","typescript"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}