{"record":{"id":"bf0dd0f949effed2","repo":"remotion-dev/remotion","slug":"dotsize-must-be-1-but-got-json-stringify-p","errorCode":null,"errorMessage":"\"dotSize\" must be >= 1, but got ${JSON.stringify(params.dotSize)}","messagePattern":"\"dotSize\" must be >= 1, but got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/effects/src/halftone.ts","lineNumber":204,"sourceCode":"\tassertOptionalEnum(params.colorMode, 'colorMode', HALFTONE_COLOR_MODES);\n\tif ('color' in params && params.color !== undefined) {\n\t\tthrow new TypeError('\"color\" has been renamed to \"dotColor\"');\n\t}\n\n\tif (params.colorMode === 'source' && 'dotColor' in params) {\n\t\tthrow new TypeError(\n\t\t\t'\"dotColor\" can only be set when \"colorMode\" is \"solid\"',\n\t\t);\n\t}\n\n\tassertOptionalColor(\n\t\t'dotColor' in params ? params.dotColor : undefined,\n\t\t'dotColor',\n\t);\n\tassertOptionalBoolean(params.invert, 'invert');\n\n\tif (params.dotSize !== undefined && params.dotSize < 1) {\n\t\tthrow new TypeError(\n\t\t\t`\"dotSize\" must be >= 1, but got ${JSON.stringify(params.dotSize)}`,\n\t\t);\n\t}\n\n\tif (params.dotSpacing !== undefined && params.dotSpacing < 1) {\n\t\tthrow new TypeError(\n\t\t\t`\"dotSpacing\" must be >= 1, but got ${JSON.stringify(params.dotSpacing)}`,\n\t\t);\n\t}\n};\n\nconst HALFTONE_VS = /* glsl */ `#version 300 es\nin vec2 aPos;\nin vec2 aUv;\nout vec2 vUv;\nvoid main() {\n\tvUv = aUv;\n\tgl_Position = vec4(aPos, 0.0, 1.0);","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/halftone.ts#L186-L222","documentation":"Thrown by validateHalftoneParams() when params.dotSize is a finite number but less than 1. The halftone schema declares dotSize with min: 1, and this runtime guard enforces the same floor because sub-pixel dot sizes produce a degenerate grid. The message echoes the offending value via JSON.stringify so the bad input is visible.","triggerScenarios":"Calling halftone({ dotSize: 0 }), halftone({ dotSize: 0.5 }), or halftone({ dotSize: -3 }). Passing NaN/Infinity is caught earlier by assertOptionalFiniteNumber, so this branch only fires for finite sub-1 numbers.","commonSituations":"Animation keyframes that ramp dotSize down to 0; math expressions like dotSize: width / 1000 that can collapse below 1 for small inputs; UI sliders without a lower bound.","solutions":["Clamp dotSize to at least 1: Math.max(1, value).","Raise the minimum of any animation keyframe that targets dotSize to 1.","If a slider drives dotSize, set its min attribute to 1."],"exampleFix":"// before\nhalftone({ dotSize: frame < 10 ? frame * 0.3 : 20 })\n\n// after\nhalftone({ dotSize: Math.max(1, frame < 10 ? frame * 0.3 : 20) })","handlingStrategy":"validation","validationCode":"function clampDotSize(v: number | undefined): number | undefined {\n  return v === undefined ? undefined : Math.max(1, v);\n}\n// then: halftone({ dotSize: clampDotSize(rawDotSize) })","typeGuard":"function isValidDotSize(v: unknown): v is number {\n  return typeof v === 'number' && Number.isFinite(v) && v >= 1;\n}","tryCatchPattern":null,"preventionTips":["Clamp any animated or computed dotSize with Math.max(1, value) before passing it in.","Set UI slider min to 1 (matching the schema's min: 1).","When deriving dotSize from another quantity, sanity-check its range first."],"tags":["halftone","validation","params","numeric","range"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}