{"record":{"id":"2d3b5466a5ecef75","repo":"heygen-com/hyperframes","slug":"expected-expectedrows-lut-rows-for-size-lut3d","errorCode":null,"errorMessage":"Expected ${expectedRows} LUT rows for size ${lut3dSize}, found ${rows.length / 3}","messagePattern":"Expected (.+?) LUT rows for size (.+?), found (.+?)","errorType":"validation","errorClass":"CubeLutParseError","httpStatus":null,"severity":"error","filePath":"packages/core/src/colorLuts.ts","lineNumber":183,"sourceCode":"    rows.push(\n      parseFiniteNumber(parts[0]!, lineNumber),\n      parseFiniteNumber(parts[1]!, lineNumber),\n      parseFiniteNumber(parts[2]!, lineNumber),\n    );\n  }\n\n  if (lut1dSize && lut3dSize) {\n    throw new CubeLutParseError(\"Mixed 1D and 3D cube LUTs are not supported yet\");\n  }\n  if (!lut3dSize) {\n    if (lut1dSize) throw new CubeLutParseError(\"1D cube LUTs are not supported yet\");\n    throw new CubeLutParseError(\"Missing LUT_3D_SIZE\");\n  }\n  validateDomain(domainMin, domainMax);\n\n  const expectedRows = lut3dSize * lut3dSize * lut3dSize;\n  if (rows.length !== expectedRows * 3) {\n    throw new CubeLutParseError(\n      `Expected ${expectedRows} LUT rows for size ${lut3dSize}, found ${rows.length / 3}`,\n    );\n  }\n\n  return {\n    title,\n    size: lut3dSize,\n    domainMin,\n    domainMax,\n    data: new Float32Array(rows),\n  };\n}\n\nfunction clampUnit(value: number): number {\n  if (!Number.isFinite(value)) return 0;\n  return Math.min(1, Math.max(0, value));\n}\n","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/core/src/colorLuts.ts#L165-L201","documentation":"After parsing, the row count must equal LUT_3D_SIZE^3 RGB triples. The check at line 182-185 rejects a mismatch between declared size and actual data volume. The message reports both the expected count and the count found (rows.length / 3). Note this throw has no lineNumber — it is a whole-file summary error.","triggerScenarios":"Declaring 'LUT_3D_SIZE 4' but providing fewer or more than 64 rows (4^3 = 64); truncating or duplicating data rows; declaring the wrong size for the body.","commonSituations":"Truncated download; an extra blank line that the parser skipped causing an off-by-one in row count; declaring size 33 but supplying a size-32 body (32768 vs 35937 rows); copy-paste duplicating a block.","solutions":["Compare the message's expected vs found counts; if found < expected, the file is truncated — re-download/re-export.","If found > expected, remove duplicate rows or raise LUT_3D_SIZE to match the body.","If the size header is wrong, correct it to cube-root of (row count), e.g. size = Math.cbrt(rows.length).","Validate before parsing: count numeric triples and assert === size*size*size."],"exampleFix":"// before — header says size 4 (expects 64 rows) but only 27 present\nLUT_3D_SIZE 4\n... 27 rows ...\n\n// after — match size to body (cube root of 27 is 3)\nLUT_3D_SIZE 3\n... 27 rows ...","handlingStrategy":"validation","validationCode":"function expectedRowCount(fileText: string): number | null {\n  const m = /^LUT_3D_SIZE\\s+(\\d+)/m.exec(fileText);\n  if (!m) return null;\n  const n = Number(m[1]);\n  return n * n * n;\n}\n\nfunction actualRowCount(fileText: string): number {\n  return fileText.split(/\\r?\\n/).filter((l) => {\n    const t = l.trim().split(/\\s+/);\n    return t.length === 3 && /^[+-]?(?:\\d|\\.\\d)/.test(t[0] ?? '');\n  }).length;\n}\n\nconst expected = expectedRowCount(fileText);\nif (expected !== null && actualRowCount(fileText) !== expected) {\n  throw new Error(`Row count mismatch: expected ${expected}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  parseCubeLut(fileText);\n} catch (err) {\n  if (err instanceof CubeLutParseError && /Expected .* LUT rows/.test(err.message)) {\n    // parse expected vs found from the message; either re-export, drop duplicates, or fix LUT_3D_SIZE\n  } else throw err;\n}","preventionTips":["Validate that numeric row count === size^3 before parsing.","Re-export truncated LUTs from the source tool rather than patching.","When generating LUTs, assert data length === size*size*size*3 at serialization time."],"tags":["lut","cube","data","count"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}