{"record":{"id":"ff8409d71b6b9ec4","repo":"heygen-com/hyperframes","slug":"missing-lut-3d-size","errorCode":null,"errorMessage":"Missing LUT_3D_SIZE","messagePattern":"Missing LUT_3D_SIZE","errorType":"validation","errorClass":"CubeLutParseError","httpStatus":null,"severity":"error","filePath":"packages/core/src/colorLuts.ts","lineNumber":177,"sourceCode":"      }\n      throw new CubeLutParseError(\"LUT data appears before LUT_3D_SIZE\", lineNumber);\n    }\n    if (parts.length !== 3) {\n      throw new CubeLutParseError(\"LUT data rows must contain three numbers\", lineNumber);\n    }\n    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}","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/core/src/colorLuts.ts#L159-L195","documentation":"Thrown by parseCubeLut after scanning the entire .cube file: no LUT_3D_SIZE (and no LUT_1D_SIZE) keyword was ever seen. The Adobe .cube spec requires a LUT_3D_SIZE header before the data table; without it the row count and packing are undefined, so the parser refuses to guess. Note this is distinct from the line-accurate 'LUT data appears before LUT_3D_SIZE' (colorLuts.ts:160) — reaching line 177 means no numeric data rows were recognised either, i.e. the file is structurally incomplete (only TITLE/DOMAIN lines, or unrecognised content).","triggerScenarios":"Calling parseCubeLut on a file that contains only a TITLE line; a file with comments/header metadata but the LUT_3D_SIZE line deleted; a file where the size line was misspelled (e.g. 'LUT3D_SIZE' or 'LUT_3D_SIZE:') so the keyword match at colorLuts.ts:142 fails and the line falls through to the generic skip at line 154; passing an empty or whitespace-only string.","commonSituations":"Truncation during download or copy-paste of a .cube file losing the trailing header; hand-authored LUT files with a typo in the keyword; feeding a 1D .cube snippet that never declared LUT_1D_SIZE; reading the wrong file (e.g. a .png or a .txt readme) whose path was mistakenly passed to parseCubeLut.","solutions":["Open the .cube file and confirm a line reads exactly 'LUT_3D_SIZE N' (N integer >= 2) appears before any numeric data rows.","If the file is a 1D LUT, note that this parser only supports 3D LUTs — convert it to a 3D .cube or use a different loader.","Check for keyword typos: the parser uppercases token[0] and compares to the literal 'LUT_3D_SIZE' (no colon, no underscores moved).","If the file came from a download/export, re-export it from the source tool (DaVinci Resolve, Photoshop, etc.) — truncation is the usual cause."],"exampleFix":"// before — header line malformed, keyword never matches\nTITLE \"my lut\"\nLUT3D_SIZE 17\n0.0 0.0 0.0\n...\n\n// after — exact keyword\nTITLE \"my lut\"\nLUT_3D_SIZE 17\n0.0 0.0 0.0\n...","handlingStrategy":"validation","validationCode":"// Pre-validate a .cube file before calling parseCubeLut\nimport { readFileSync } from 'node:fs';\nexport function assertCubeHasSize(path: string): void {\n  const text = readFileSync(path, 'utf-8');\n  const has3d = /^LUT_3D_SIZE\\s+\\d+/im.test(text);\n  const has1d = /^LUT_1D_SIZE\\s+\\d+/im.test(text);\n  if (!has3d && !has1d) {\n    throw new Error(`${path} has no LUT_3D_SIZE / LUT_1D_SIZE header`);\n  }\n}","typeGuard":null,"tryCatchPattern":"import { parseCubeLut, CubeLutParseError } from '.../colorLuts';\ntry {\n  const lut = parseCubeLut(text);\n} catch (err) {\n  if (err instanceof CubeLutParseError && /Missing LUT_3D_SIZE/.test(err.message)) {\n    // surface a 're-export the .cube with a size header' message to the user\n  } else throw err;\n}","preventionTips":["Always re-export .cube files from a known tool (DaVinci/Photoshop) rather than hand-editing headers.","When accepting user-supplied LUTs, run the header pre-check above so the error message is user-friendly.","Keep LUT files out of version-control truncation by checking file size on read."],"tags":["lut","cube","parsing","color-grading"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}