{"record":{"id":"db3492efc4f5dc1a","repo":"remotion-dev/remotion","slug":"scale-must-be-greater-than-0-but-got-json-str","errorCode":null,"errorMessage":"\"scale\" must be greater than 0, but got ${JSON.stringify(r.scale)}","messagePattern":"\"scale\" must be greater than 0, but got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/effects/src/paper.ts","lineNumber":321,"sourceCode":"\tassertOptionalFiniteNumber(params.scale, 'scale');\n\n\tconst r = resolve(params);\n\tvalidateUnitInterval(r.amount, 'amount');\n\tvalidateUnitInterval(r.contrast, 'contrast');\n\tvalidateUnitInterval(r.roughness, 'roughness');\n\tvalidateUnitInterval(r.fiber, 'fiber');\n\tvalidatePositiveUnitInterval(r.fiberSize, 'fiberSize');\n\tvalidateUnitInterval(r.crumples, 'crumples');\n\tvalidatePositiveUnitInterval(r.crumpleSize, 'crumpleSize');\n\tvalidateUnitInterval(r.folds, 'folds');\n\tvalidateNonNegative(r.foldCount, 'foldCount');\n\tvalidateAtMost(r.foldCount, MAX_FOLD_COUNT, 'foldCount');\n\tvalidateUnitInterval(r.drops, 'drops');\n\tvalidateUnitInterval(r.fade, 'fade');\n\tvalidateNonNegative(r.seed, 'seed');\n\tvalidateAtMost(r.seed, MAX_SEED, 'seed');\n\tif (r.scale <= 0) {\n\t\tthrow new TypeError(\n\t\t\t`\"scale\" must be greater than 0, but got ${JSON.stringify(r.scale)}`,\n\t\t);\n\t}\n\n\tvalidateAtMost(r.scale, 4, 'scale');\n};\n\nconst PAPER_VS = /* glsl */ `#version 300 es\nin vec2 aPos;\nin vec2 aUv;\nout vec2 vUv;\n\nvoid main() {\n\tvUv = aUv;\n\tgl_Position = vec4(aPos, 0.0, 1.0);\n}\n`;\n","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/paper.ts#L303-L339","documentation":"Thrown by an explicit inline check in validatePaperParams (packages/effects/src/paper.ts:321) when the resolved scale is ≤ 0. scale controls the paper-pattern zoom (documented 0.01–4) and is used as a divisor in the shader (max(uScale, 0.001)), so zero/negative is rejected before setup to avoid a degenerate render.","triggerScenarios":"Calling paper({scale: 0}) or paper({scale: -1}); animating scale down to zero without clamping.","commonSituations":"An interpolate ramping scale to 0; a UI default of 0 copied into params; math producing 0 from a division.","solutions":["Set scale to a positive value in (0, 4] (minimum 0.01).","Clamp animations to a small positive floor: Math.max(0.01, value) or interpolate with extrapolateLeft: 'clamp'.","Pre-validate scale > 0 with the guard below."],"exampleFix":"// before\npaper({scale: 0}); // throws\n\n// after\npaper({scale: 0.01});","handlingStrategy":"validation","validationCode":"// Ensure scale is in (0, 4]\nfunction sanitizePaperScale(v: number | undefined): number | undefined {\n  if (v === undefined) return undefined;\n  if (typeof v !== 'number' || !Number.isFinite(v) || v <= 0) return 0.01;\n  return Math.min(v, 4);\n}\n\n// usage: paper({scale: sanitizePaperScale(raw.scale)})","typeGuard":"const isValidPaperScale = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isFinite(v) && v > 0 && v <= 4;","tryCatchPattern":"try {\n  paper({scale: raw.scale});\n} catch (err) {\n  if (err instanceof TypeError && /\"scale\" must be greater than 0/.test(err.message)) {\n    paper({scale: Math.max(0.01, raw.scale)});\n  } else throw err;\n}","preventionTips":["Floor animated scale at 0.01 with Math.max or extrapolateLeft: 'clamp'.","Validate externally sourced scale before calling paper().","Ensure UI scale controls start above zero."],"tags":["validation","params","paper","effects","range","scale"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}