{"record":{"id":"aeb63ab7d6a4fc6f","repo":"remotion-dev/remotion","slug":"columns-must-be-1-but-got-json-stringify-r","errorCode":null,"errorMessage":"\"columns\" must be >= 1, but got ${JSON.stringify(r.columns)}","messagePattern":"\"columns\" must be >= 1, but got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/effects/src/pixel-dissolve.ts","lineNumber":114,"sourceCode":"\t}\n};\n\nconst validatePixelDissolveParams = (params: PixelDissolveParams): void => {\n\tassertEffectParamsObject(params, 'Pixel Dissolve');\n\tassertOptionalFiniteNumber(params.progress, 'progress');\n\tassertOptionalFiniteNumber(params.columns, 'columns');\n\tassertOptionalFiniteNumber(params.rows, 'rows');\n\tassertOptionalFiniteNumber(params.seed, 'seed');\n\tassertOptionalFiniteNumber(params.feather, 'feather');\n\tassertOptionalIntegerNumber(params.columns, 'columns');\n\tassertOptionalIntegerNumber(params.rows, 'rows');\n\n\tconst r = resolve(params);\n\tvalidateUnitInterval(r.progress, 'progress');\n\tvalidateUnitInterval(r.feather, 'feather');\n\n\tif (r.columns < 1) {\n\t\tthrow new TypeError(\n\t\t\t`\"columns\" must be >= 1, but got ${JSON.stringify(r.columns)}`,\n\t\t);\n\t}\n\n\tif (r.rows < 1) {\n\t\tthrow new TypeError(\n\t\t\t`\"rows\" must be >= 1, but got ${JSON.stringify(r.rows)}`,\n\t\t);\n\t}\n};\n\ntype PixelDissolveState = {\n\treadonly gl: WebGL2RenderingContext;\n\treadonly program: WebGLProgram;\n\treadonly vao: WebGLVertexArrayObject;\n\treadonly vbo: WebGLBuffer;\n\treadonly texture: WebGLTexture;\n\treadonly uSource: WebGLUniformLocation | null;","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/pixel-dissolve.ts#L96-L132","documentation":"pixelDissolve() requires 'columns' to be at least 1 after defaults are applied (default is 10). The check fires after integer/finite validation, throwing a TypeError showing the resolved value when columns < 1, so a zero/negative grid never reaches the shader.","triggerScenarios":"Calling pixelDissolve({ columns: 0 }) or pixelDissolve({ columns: -3 }), or animating columns down to zero/negative. Checked on the resolved value in validatePixelDissolveParams.","commonSituations":"Animating columns toward zero to 'disable' the effect; negative values from inverted config; unit conversion producing zero at boundary frames.","solutions":["Keep columns >= 1 (documented range is 1..400).","Clamp animated values: Math.max(1, Math.round(value)).","To remove the effect, animate progress to 0/1 or drop the effect from the stack rather than zeroing columns."],"exampleFix":"// before\npixelDissolve({ columns: animatedCols }) // hits 0\n\n// after\npixelDissolve({ columns: Math.max(1, Math.round(animatedCols)) })","handlingStrategy":"validation","validationCode":"// Keep columns within the documented range.\nconst columns = clamp(Math.round(rawColumns), 1, 400);\npixelDissolve({ columns });\n// where clamp(n, lo, hi) = Math.min(hi, Math.max(lo, n))","typeGuard":"const isValidColumns = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isInteger(v) && v >= 1;","tryCatchPattern":null,"preventionTips":["Clamp animated columns with Math.max(1, Math.round(value)).","Fade the effect via the 'progress' prop instead of zeroing columns.","Reject zero/negative values from external config at the boundary.","Validate against the schema min (1) and max (400) before rendering."],"tags":["validation","typescript","pixel-dissolve","range","params"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}