{"record":{"id":"82fd3bf2b0dd83dd","repo":"BabylonJS/Babylon.js","slug":"attempted-to-get-an-invalid-layout-column","errorCode":null,"errorMessage":"Attempted to get an invalid layout column","messagePattern":"Attempted to get an invalid layout column","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/sharedUiComponents/src/components/layout/utils.ts","lineNumber":17,"sourceCode":"import { type Layout, type LayoutColumn, type LayoutTabsRow } from \"./types\";\r\n\r\n/**\r\n * Given a column and row number in the layout, return the corresponding column/row\r\n * @param layout\r\n * @param column\r\n * @param row\r\n * @returns\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport const getPosInLayout = (layout: Layout, column: number, row?: number): LayoutColumn | LayoutTabsRow => {\r\n    if (!layout.columns) {\r\n        throw new Error(\"Attempted to get position on empty layout\");\r\n    }\r\n    const columnLayout = layout.columns[column];\r\n    if (!columnLayout) {\r\n        throw new Error(\"Attempted to get an invalid layout column\");\r\n    }\r\n    if (row === undefined) {\r\n        return columnLayout;\r\n    }\r\n    return columnLayout.rows[row];\r\n};\r\n\r\n/**\r\n * Remove a row in position row, column from the layout, and redistribute heights of remaining rows\r\n * @param layout\r\n * @param column\r\n * @param row\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport const removeLayoutRowAndRedistributePercentages = (layout: Layout, column: number, row: number) => {\r\n    if (!layout.columns) {\r\n        throw new Error(\"Attempted to get position on empty layout\");\r\n    }\r","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/sharedUiComponents/src/components/layout/utils.ts#L1-L35","documentation":"getPosInLayout looks up layout.columns[column]; if that index does not exist (undefined), the requested column is out of bounds or missing and the function throws rather than returning undefined, keeping layout consumers from operating on invalid data.","triggerScenarios":"Calling getPosInLayout(layout, column) where column is >= layout.columns.length, negative, or points to a deleted column — e.g. saving a stale column index and applying it to a smaller/rebuilt layout.","commonSituations":"Restoring a persisted layout after the number of columns changed between app versions; stale UI state referencing removed panes; off-by-one indexing when iterating columns.","solutions":["Validate the column index (0 <= column < layout.columns.length) before calling","Clamp or recompute the index from the current layout instead of cached state","Migrate/re-validate persisted layout JSON against the current schema on load","try/catch the call and fall back to column 0 or a default layout"],"exampleFix":"// before\nconst col = getPosInLayout(layout, savedIndex); // savedIndex may exceed layout.columns.length\n// after\nconst idx = Math.min(savedIndex, layout.columns.length - 1);\nconst col = getPosInLayout(layout, Math.max(idx, 0));","handlingStrategy":"validation","validationCode":"function isValidColumn(layout: Layout, column: number): boolean {\n    return !!layout.columns && column >= 0 && column < layout.columns.length && !!layout.columns[column];\n}\n// usage\nif (isValidColumn(layout, idx)) { getPosInLayout(layout, idx); }","typeGuard":null,"tryCatchPattern":"try {\n    const col = getPosInLayout(layout, idx);\n} catch (e) {\n    if (e instanceof Error && e.message === \"Attempted to get an invalid layout column\") {\n        // clamp index or reload a valid default layout\n    } else { throw e; }\n}","preventionTips":["Never reuse stale column indices saved from a previous layout shape; re-derive them","Clamp indices: Math.min(idx, layout.columns.length - 1)","Migrate persisted layout settings when the number of columns changes between versions","Verify layout state after any add/remove column operation before further lookups"],"tags":["ui","layout","index-out-of-bounds","shared-ui"],"backgroundTag":"layout-index-out-of-bounds","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}