{"record":{"id":"6a946bc2ed574eca","repo":"makeplane/plane","slug":"invalid-valuestop-anchorstop-must-be-one-of","errorCode":null,"errorMessage":"Invalid valueStop: ${anchorStop}. Must be one of ${SHADE_STOPS.join(\", \")}","messagePattern":"Invalid valueStop: (.+?)\\. Must be one of (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/utils/src/theme/palette-generator.ts","lineNumber":142,"sourceCode":"  const inputOKLCH = hexToOKLCH(normalizedHex);\n  const { l: inputL, c: inputC, h: inputH } = inputOKLCH;\n\n  const DEFAULT_LIGHTNESS_MIN = mode === \"light\" ? DEFAULT_LIGHT_MODE_LIGHTNESS_MIN : DEFAULT_DARK_MODE_LIGHTNESS_MIN;\n  const DEFAULT_LIGHTNESS_MAX = mode === \"light\" ? DEFAULT_LIGHT_MODE_LIGHTNESS_MAX : DEFAULT_DARK_MODE_LIGHTNESS_MAX;\n\n  // Extract options with defaults\n  const {\n    lightnessMin = DEFAULT_LIGHTNESS_MIN / 100, // Convert to 0-1 scale\n    lightnessMax = DEFAULT_LIGHTNESS_MAX / 100, // Convert to 0-1 scale\n    valueStop = options.valueStop ?? DEFAULT_VALUE_STOP,\n  } = options;\n\n  // Calculate or use provided valueStop\n  const anchorStop = valueStop === \"auto\" ? calculateDynamicValueStop(inputOKLCH) : valueStop;\n\n  // Validate valueStop if provided manually\n  if (typeof anchorStop === \"number\" && !isValidShadeStop(anchorStop)) {\n    throw new Error(`Invalid valueStop: ${anchorStop}. Must be one of ${SHADE_STOPS.join(\", \")}`);\n  }\n\n  // Create lightness distribution with three anchor points\n  const distributionAnchors = [\n    { stop: SHADE_STOPS[0], lightness: lightnessMax }, // Lightest\n    { stop: anchorStop, lightness: inputL }, // Input color\n    { stop: SHADE_STOPS[SHADE_STOPS.length - 1], lightness: lightnessMin }, // Darkest\n  ];\n\n  // Generate palette by interpolating lightness for each stop\n  const palette: Partial<ColorPalette> = {};\n\n  SHADE_STOPS.forEach((stop) => {\n    let targetLightness: number;\n\n    // Check if this is an anchor point\n    const anchor = distributionAnchors.find((a) => a.stop === stop);\n    if (anchor) {","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/makeplane/plane/blob/1c8a60f858d8472aa56e29994ec1c7926da2c6ce/packages/utils/src/theme/palette-generator.ts#L124-L160","documentation":"When options.valueStop is provided as a number (not 'auto'), generateColorPalette checks it against SHADE_STOPS via isValidShadeStop. The valueStop is the shade anchor (the stop whose lightness equals the input color); it must be one of the supported stops. 'auto' skips this check and computes a dynamic stop; an out-of-range number is rejected.","triggerScenarios":"generateColorPalette(color, 'light', { valueStop: 99 }); generateColorPalette(color, 'light', { valueStop: 0 } if 0 is not in SHADE_STOPS); any numeric valueStop outside SHADE_STOPS.","commonSituations":"Hard-coding a valueStop from an older version when SHADE_STOPS changed; config file with a typo; copy-pasted options from another theme tool with a different scale.","solutions":["Use { valueStop: 'auto' } unless you have a specific reason to pin.","If pinning, pick from SHADE_STOPS (import and reference the array rather than hard-coding).","Validate the configured valueStop on app boot and reset to a valid default."],"exampleFix":"// before\ngenerateColorPalette(color, 'light', { valueStop: 99 });\n\n// after\nimport { SHADE_STOPS } from './theme/palette-generator';\nconst stop = SHADE_STOPS.includes(config.valueStop) ? config.valueStop : 'auto';\ngenerateColorPalette(color, 'light', { valueStop: stop });","handlingStrategy":"validation","validationCode":"import { SHADE_STOPS } from './theme/palette-generator';\nconst stop = options.valueStop === 'auto' || (typeof options.valueStop === 'number' && SHADE_STOPS.includes(options.valueStop)) ? options.valueStop : 'auto';","typeGuard":"function isValidStop(s: unknown): boolean { return s === 'auto' || (typeof s === 'number' && SHADE_STOPS.includes(s as number)); }","tryCatchPattern":"try { generateColorPalette(c, 'light', { valueStop }); } catch (e) { if (/Invalid valueStop/.test((e as Error).message)) { generateColorPalette(c, 'light', { valueStop: 'auto' }); } else throw e; }","preventionTips":["Prefer valueStop: 'auto'","Reference SHADE_STOPS instead of hard-coding","Validate theme config on app boot"],"tags":["theme","color","validation","palette-generator","config"],"backgroundTag":null,"analyzedSha":"1c8a60f858d8472aa56e29994ec1c7926da2c6ce","analyzedAt":"2026-08-12T14:44:31.636Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}