{"record":{"id":"6ad3e47649ca0eaf","repo":"heygen-com/hyperframes","slug":"keyword-expects-three-numbers","errorCode":null,"errorMessage":"${keyword} expects three numbers","messagePattern":"(.+?) expects three numbers","errorType":"validation","errorClass":"CubeLutParseError","httpStatus":null,"severity":"error","filePath":"packages/core/src/colorLuts.ts","lineNumber":55,"sourceCode":"  for (let i = 0; i < line.length; i++) {\n    const char = line[i];\n    if (char === '\"') inQuote = !inQuote;\n    if (char === \"#\" && !inQuote) return line.slice(0, i);\n  }\n  return line;\n}\n\nfunction parseFiniteNumber(value: string, lineNumber: number): number {\n  const parsed = Number(value);\n  if (!Number.isFinite(parsed)) {\n    throw new CubeLutParseError(`Invalid number \"${value}\"`, lineNumber);\n  }\n  return parsed;\n}\n\nfunction parseVec3(parts: string[], keyword: string, lineNumber: number): CubeLutVec3 {\n  if (parts.length !== 3) {\n    throw new CubeLutParseError(`${keyword} expects three numbers`, lineNumber);\n  }\n  return [\n    parseFiniteNumber(parts[0]!, lineNumber),\n    parseFiniteNumber(parts[1]!, lineNumber),\n    parseFiniteNumber(parts[2]!, lineNumber),\n  ];\n}\n\nfunction parseSize(value: string | undefined, keyword: string, lineNumber: number): number {\n  if (!value) throw new CubeLutParseError(`${keyword} expects a size`, lineNumber);\n  const parsed = Number(value);\n  if (!Number.isInteger(parsed) || parsed < 2) {\n    throw new CubeLutParseError(`${keyword} must be an integer greater than 1`, lineNumber);\n  }\n  return parsed;\n}\n\nfunction validateDomain(domainMin: CubeLutVec3, domainMax: CubeLutVec3): void {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/core/src/colorLuts.ts#L37-L73","documentation":"parseVec3 expects exactly three whitespace-separated numbers after DOMAIN_MIN or DOMAIN_MAX (one per RGB channel). The throw at line 55 fires when the token count is not three, before any token is parsed as a number.","triggerScenarios":"A .cube line like 'DOMAIN_MIN 0 0' (two values), 'DOMAIN_MIN 0 0 0 0' (four), or 'DOMAIN_MIN' (none).","commonSituations":"Hand-edited header with a missing channel; copy-paste from a 1D LUT spec; a stray extra column from a spreadsheet export.","solutions":["Ensure each DOMAIN_MIN / DOMAIN_MAX line has exactly three numeric tokens.","If you want a uniform domain, repeat the same value three times (e.g. 'DOMAIN_MIN 0 0 0').","Re-export the LUT from the originating color tool."],"exampleFix":"// before\nDOMAIN_MIN 0 0\nDOMAIN_MAX 1 1 1\n\n// after\nDOMAIN_MIN 0 0 0\nDOMAIN_MAX 1 1 1","handlingStrategy":"try-catch","validationCode":"function assertVec3Header(line: string): void {\n  const parts = line.trim().split(/\\s+/);\n  const keyword = (parts[0] ?? '').toUpperCase();\n  if ((keyword === 'DOMAIN_MIN' || keyword === 'DOMAIN_MAX') && parts.length !== 4) {\n    throw new Error(`${keyword} needs 3 numbers, got ${parts.length - 1}`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  parseCubeLut(fileText);\n} catch (err) {\n  if (err instanceof CubeLutParseError && /expects three numbers/.test(err.message)) {\n    // point user at the header line in err.lineNumber\n  } else throw err;\n}","preventionTips":["Keep DOMAIN_MIN / DOMAIN_MAX lines as three whitespace-separated numbers.","Use LUT_3D_INPUT_RANGE (2 scalars) only if you want a uniform domain.","Re-export rather than hand-author header lines."],"tags":["lut","cube","parsing","domain"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}