{"record":{"id":"54efefcb79a7b106","repo":"apache/echarts","slug":"levels-i-depth-is-mandatory-and-should-be-natural","errorCode":null,"errorMessage":"levels[i].depth is mandatory and should be natural number","messagePattern":"levels\\[i\\]\\.depth is mandatory and should be natural number","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/chart/sankey/SankeySeries.ts","lineNumber":191,"sourceCode":"    layoutInfo: LayoutRect;\n\n    /**\n     * Init a graph data structure from data in option series\n     */\n    getInitialData(option: SankeySeriesOption, ecModel: GlobalModel) {\n        const links = option.edges || option.links || [];\n        const nodes = option.data || option.nodes || [];\n        const levels = option.levels || [];\n        this.levelModels = [];\n        const levelModels = this.levelModels;\n\n        for (let i = 0; i < levels.length; i++) {\n            if (levels[i].depth != null && levels[i].depth >= 0) {\n                levelModels[levels[i].depth] = new Model(levels[i], this, ecModel);\n            }\n            else {\n                if (__DEV__) {\n                    throw new Error('levels[i].depth is mandatory and should be natural number');\n                }\n            }\n        }\n\n        const graph = createGraphFromNodeEdge(nodes, links, this, true, beforeLink);\n        return graph.data;\n\n        function beforeLink(nodeData: SeriesData, edgeData: SeriesData) {\n            nodeData.wrapMethod('getItemModel', function (model: Model, idx: number) {\n                const seriesModel = model.parentModel as SankeySeriesModel;\n                const layout = seriesModel.getData().getItemLayout(idx);\n                if (layout) {\n                    const nodeDepth = layout.depth;\n                    const levelModel = seriesModel.levelModels[nodeDepth];\n                    if (levelModel) {\n                        model.parentModel = levelModel;\n                    }\n                }","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/apache/echarts/blob/30076aedcd7b7f65d8dd8e8d9ece46ce778133a3/src/chart/sankey/SankeySeries.ts#L173-L209","documentation":"DEV-only guard in SankeySeries data init: each entry in option.levels must carry a depth that is a natural number (>= 0). depth maps the level config to a specific layer of the sankey; missing or negative depth makes the level unplaceable, so dev builds reject it.","triggerScenarios":"levels: [{ ... }, { depth: undefined }, { depth: -1 }] — any entry with missing/null/non-numeric depth, or depth < 0.","commonSituations":"Trimmed/serialized sankey config that dropped the depth field; copying level config from another chart; partially authored levels arrays.","solutions":["Ensure every levels entry has depth as an integer >= 0","Use consecutive depths 0..N matching your node layers","Drop level entries you cannot assign a depth to"],"exampleFix":"// before\nlevels: [{ itemStyle: { color: '#ccc' } }]\n\n// after\nlevels: [\n  { depth: 0, itemStyle: { color: '#ccc' } },\n  { depth: 1, itemStyle: { color: '#999' } }\n]","handlingStrategy":"validation","validationCode":"(option.levels || []).forEach((l: any, i: number) => {\n  if (!(l && l.depth != null && l.depth >= 0)) {\n    console.error('[sankey] levels[' + i + '].depth missing or invalid');\n  }\n});","typeGuard":"const hasValidDepth = (l: any): boolean =>\n  l != null && l.depth != null && typeof l.depth === 'number' && l.depth >= 0;","tryCatchPattern":null,"preventionTips":["Always set depth on each sankey level entry","Use consecutive non-negative integers for depth","Validate the levels array before setOption"],"tags":["sankey","levels","configuration","dev-only"],"backgroundTag":null,"analyzedSha":"30076aedcd7b7f65d8dd8e8d9ece46ce778133a3","analyzedAt":"2026-08-12T12:42:28.134Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}