{"record":{"id":"0c81eeef5eef0b57","repo":"BabylonJS/Babylon.js","slug":"missing-codebook-in-sog-version-2-scales-data","errorCode":null,"errorMessage":"Missing codebook in SOG version 2 scales data.","messagePattern":"Missing codebook in SOG version 2 scales data\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/dev/loaders/src/SPLAT/sog.pure.ts","lineNumber":187,"sourceCode":"    // --- Positions\r\n    for (let i = 0; i < splatCount; i++) {\r\n        const index = i * 4;\r\n        for (let j = 0; j < 3; j++) {\r\n            const meansMin = data.means.mins[j];\r\n            const meansMax = data.means.maxs[j];\r\n            const meansup = meansu[index + j];\r\n            const meanslow = meansl[index + j];\r\n            const q = (meansup << 8) | meanslow;\r\n            const n = Scalar.Lerp(meansMin, meansMax, q / 65535);\r\n            position[i * 8 + j] = unlog(n);\r\n        }\r\n    }\r\n\r\n    // --- Scales\r\n    const scales = imageDataArrays[2].bits;\r\n    if (data.version === 2) {\r\n        if (!data.scales.codebook) {\r\n            throw new Error(\"Missing codebook in SOG version 2 scales data.\");\r\n        }\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const index = i * 4;\r\n            for (let j = 0; j < 3; j++) {\r\n                const sc = data.scales.codebook[scales[index + j]];\r\n                const sce = Math.exp(sc);\r\n                scale[i * 8 + 3 + j] = sce;\r\n            }\r\n        }\r\n    } else {\r\n        if (!Array.isArray(data.scales.mins) || !Array.isArray(data.scales.maxs)) {\r\n            throw new Error(\"Missing arrays in SOG scales data.\");\r\n        }\r\n\r\n        for (let i = 0; i < splatCount; i++) {\r\n            const index = i * 4;\r\n            for (let j = 0; j < 3; j++) {\r\n                const sc = scales[index + j];\r","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/SPLAT/sog.pure.ts#L169-L205","documentation":"ParseSogDatas decodes SOG (Sparse Occupancy Grid / splat) scales by indexing a codebook palette (data.scales.codebook) when the meta.json declares format version 2. This error means the version field says 2 (codebook-quantized encoding) but the scales entry in meta.json has no codebook array, so the uint8 indices in the scales image cannot be mapped to real scale values. The library throws rather than silently producing garbage scale values.","triggerScenarios":"Calling ParseSogMeta (or ParseSogMetaAsTextures) with a meta.json where version: 2 while data.scales lacks the codebook property — typically because the meta.json was hand-edited, produced by an encoder targeting SOG v1, or the codebook key was dropped when transcribing/transforming the metadata.","commonSituations":"Mixing SOG v1 and v2 assets (v1 meta has mins/maxs, v2 requires codebook); an asset pipeline upgrade that bumped version to 2 without regenerating meta.json; custom tooling that strips unknown fields from meta.json; loading a partially-uploaded SOG bundle where meta.json is from one version and images from another.","solutions":["Regenerate meta.json with a SOG v2 encoder so data.scales.codebook is populated.","If the asset is actually v1, remove version: 2 (or set version: 1) from meta.json so the mins/maxs path is used instead.","Validate meta.json before parsing: if version === 2, check Array.isArray(data.scales.codebook) before calling ParseSogMeta."],"exampleFix":"// before (meta.json)\n{ \"version\": 2, \"scales\": { \"shape\": [...], \"dtype\": \"uint8\", \"files\": [\"scales.webp\"] } }\n// after\n{ \"version\": 2, \"scales\": { \"shape\": [...], \"dtype\": \"uint8\", \"files\": [\"scales.webp\"], \"codebook\": [0.01, 0.015, ...] } }","handlingStrategy":"validation","validationCode":"function validateV2Scales(meta) {\n  if (meta.version === 2 && !Array.isArray(meta.scales?.codebook)) {\n    throw new Error('v2 SOG asset: meta.scales.codebook is required');\n  }\n}\n// call validateV2Scales(meta) before ParseSogMeta(meta, rootUrl, scene)","typeGuard":"function hasScalesCodebook(meta) {\n  return meta.version !== 2 || Array.isArray(meta.scales?.codebook);\n}","tryCatchPattern":"try {\n  await ParseSogMeta(metaOrFiles, rootUrl, scene);\n} catch (e) {\n  if (e.message.includes('Missing codebook')) {\n    // asset metadata incompatible with declared version: re-export or fix meta.json\n  }\n  throw e;\n}","preventionTips":["Never hand-edit meta.json version fields; regenerate assets with the encoder when changing format version.","Add a lint step in your asset pipeline asserting v2 assets carry codebook arrays for scales/sh0/shN.","Keep meta.json and webp images from the same export together (checksum or manifest)."],"tags":["sog","gaussian-splatting","codebook","metadata","asset-validation"],"backgroundTag":"missing-codebook-in-quantized-data","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}