{"record":{"id":"06fd03687b4893e5","repo":"remotion-dev/remotion","slug":"lut-header-after-color-data-on-line-index-1","errorCode":null,"errorMessage":"LUT header after color data on line ${index + 1}.","messagePattern":"LUT header after color data on line (.+?)\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/studio/src/helpers/cube-lut.ts","lineNumber":35,"sourceCode":"\tlet domainMax: Rgb = [1, 1, 1];\n\tlet data: Float32Array | null = null;\n\tlet offset = 0;\n\tconst headers = new Set<string>();\n\n\tfor (const [index, rawLine] of text.split(/\\r\\n?|\\n/).entries()) {\n\t\tconst line = rawLine.trim();\n\t\tif (!line || line.startsWith('#')) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst titleMatch = line.match(/^TITLE\\s+\"([^\"]*)\"\\s*(?:#.*)?$/);\n\t\tconst [keyword, ...values] = line.replace(/#.*$/, '').trim().split(/\\s+/);\n\t\tconst numbers = values.map(Number);\n\t\tconst isHeader = /^[A-Z][A-Z0-9_]*$/.test(keyword);\n\n\t\tif (isHeader) {\n\t\t\tif (offset > 0) {\n\t\t\t\tthrow new Error(`LUT header after color data on line ${index + 1}.`);\n\t\t\t}\n\n\t\t\tif (headers.has(keyword)) {\n\t\t\t\tthrow new Error(`Duplicate ${keyword} on line ${index + 1}.`);\n\t\t\t}\n\n\t\t\theaders.add(keyword);\n\t\t}\n\n\t\tif (keyword === 'TITLE' && titleMatch) {\n\t\t\ttitle = titleMatch[1];\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (keyword === 'LUT_1D_SIZE' || keyword === 'LUT_3D_SIZE') {\n\t\t\tif (type !== null) {\n\t\t\t\tthrow new Error('Combined 1D and 3D LUTs are not supported.');\n\t\t\t}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/remotion-dev/remotion/blob/46a3a6bf13ca367376ff18bbb06dae2e87e0d068/packages/studio/src/helpers/cube-lut.ts#L17-L53","documentation":"parseCubeLut parses .cube LUT files and requires all header keywords (TITLE, LUT_3D_SIZE, DOMAIN_MIN, etc.) to appear before any color data lines. A header keyword found after color rows has started means a malformed file, so it throws with the offending line number.","triggerScenarios":"Loading a .cube file where a line matching /^[A-Z][A-Z0-9_]*$/ appears after numeric color rows — e.g. LUT_3D_SIZE or DOMAIN_MAX declared below the data table, or a data line accidentally formatted as an uppercase keyword.","commonSituations":"Hand-edited LUT files with the size header moved below the data; LUTs exported by broken tools; concatenated LUT files with a second header block at the end.","solutions":["Edit the .cube file so all header keywords (TITLE, LUT_*_SIZE, DOMAIN_MIN/MAX) come before the color data.","Re-export the LUT from its original tool in valid .cube format.","Check the reported line number and remove or move the misplaced header line.","Validate the file with another .cube parser to locate structural problems."],"exampleFix":"// before (broken)\n0.1 0.2 0.3\nLUT_3D_SIZE 2\n// after\nLUT_3D_SIZE 2\n0.1 0.2 0.3","handlingStrategy":"validation","validationCode":"const headerRe = /^[A-Z][A-Z0-9_]*$/;\nlet seenData = false;\nfor (const [i, line] of lines.entries()) {\n  const kw = line.split(/\\s+/)[0];\n  if (seenData && headerRe.test(kw)) throw new Error(`Header after data at line ${i + 1}`);\n  if (/^[\\d.-]+\\s+[\\d.-]+\\s+[\\d.-]+$/.test(line)) seenData = true;\n}","typeGuard":"null","tryCatchPattern":"try {\n  parseCubeLut(text);\n} catch (err) {\n  if (err.message.includes('header after color data')) {\n    // show file/line error to user or attempt reordering repair\n  }\n}","preventionTips":["Validate .cube structure before loading (headers first)","Never hand-edit header positions in LUT files","Re-export from trusted tools rather than editing exported files"],"tags":["lut","parsing","validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"46a3a6bf13ca367376ff18bbb06dae2e87e0d068","analyzedAt":"2026-09-18T00:12:20.256Z","contentChangedAt":"2026-09-18T00:12:20.256Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}