{"record":{"id":"3d352339e10edb57","repo":"remotion-dev/remotion","slug":"name-must-be-0-but-got-json-stringify-v-3d3523","errorCode":null,"errorMessage":"\"${name}\" must be >= 0, but got ${JSON.stringify(value)}","messagePattern":"\"(.+?)\" must be >= 0, but got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/effects/src/halftone-linear-gradient.ts","lineNumber":196,"sourceCode":"): HalftoneLinearGradientResolved => ({\n\tfirstStopDotSize: p.firstStopDotSize ?? DEFAULT_FIRST_STOP_DOT_SIZE,\n\tsecondStopDotSize: p.secondStopDotSize ?? DEFAULT_SECOND_STOP_DOT_SIZE,\n\tfirstStopPosition: [\n\t\t...(p.firstStopPosition ?? DEFAULT_FIRST_STOP_POSITION),\n\t] as UvCoordinate,\n\tsecondStopPosition: [\n\t\t...(p.secondStopPosition ?? DEFAULT_SECOND_STOP_POSITION),\n\t] as UvCoordinate,\n\tgridSize: p.gridSize ?? DEFAULT_GRID_SIZE,\n\tcolorMode: p.colorMode ?? 'solid',\n\tdotColor:\n\t\t'dotColor' in p ? (p.dotColor ?? DEFAULT_DOT_COLOR) : DEFAULT_DOT_COLOR,\n\tmaskToSourceAlpha: p.maskToSourceAlpha ?? DEFAULT_MASK_TO_SOURCE_ALPHA,\n});\n\nconst validateNonNegative = (value: number, name: string): void => {\n\tif (value < 0) {\n\t\tthrow new TypeError(\n\t\t\t`\"${name}\" must be >= 0, but got ${JSON.stringify(value)}`,\n\t\t);\n\t}\n};\n\nconst validatePositive = (value: number, name: string): void => {\n\tif (value <= 0) {\n\t\tthrow new TypeError(\n\t\t\t`\"${name}\" must be greater than 0, but got ${JSON.stringify(value)}`,\n\t\t);\n\t}\n};\n\nconst assertOptionalUvCoordinate = (value: unknown, name: string): void => {\n\tif (value === undefined) {\n\t\treturn;\n\t}\n","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/halftone-linear-gradient.ts#L178-L214","documentation":"TypeError thrown by halftone-linear-gradient's validateNonNegative (halftone-linear-gradient.ts:194) when a value allowed to be zero is negative. It guards firstStopDotSize and secondStopDotSize (the dot radius at each gradient stop). Zero dots are valid (no dot), negatives are not.","triggerScenarios":"validateHalftoneLinearGradientParams runs validateNonNegative on firstStopDotSize (line 252) and secondStopDotSize (line 256) when those params are provided. Triggered by passing either stop's dot size as a negative finite number.","commonSituations":"A spring/interpolation dipping below zero; deriving dot size from an offset that goes negative; a sign typo; reusing a value calibrated for a different effect whose range differs.","solutions":["Pass dot sizes as 0 or positive numbers.","Clamp animated values: Math.max(0, value).","If you meant 'no dots at this stop', use 0 explicitly."],"exampleFix":"// before\n<halftoneLinearGradient firstStopDotSize={spring.value - 4} />\n// spring can drop below 4 -> negative\n\n// after\n<halftoneLinearGradient firstStopDotSize={Math.max(0, spring.value - 4)} />","handlingStrategy":"validation","validationCode":"const clampDotSize = (v: number | undefined): number =>\n  Math.max(0, v ?? 0);\nparams.firstStopDotSize = clampDotSize(params.firstStopDotSize);\nparams.secondStopDotSize = clampDotSize(params.secondStopDotSize);","typeGuard":"const isNonNegativeFinite = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isFinite(v) && v >= 0;","tryCatchPattern":"null","preventionTips":["Clamp animated dot sizes with Math.max(0, value).","Use 0 explicitly to mean 'no dot'.","Watch spring overshoot below zero."],"tags":["halftone-linear-gradient-effect","validation","typescript","params"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}