{"record":{"id":"73025f5f18051e07","repo":"wagoodman/dive","slug":"invalid-layer-index-given-d-of-d","errorCode":null,"errorMessage":"invalid layer index given: %d of %d","messagePattern":"invalid layer index given: (.+?) of (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/dive/cli/internal/ui/v1/viewmodel/filetree.go","lineNumber":111,"sourceCode":"\treturn vm.bufferIndexLowerBound + vm.height()\n}\n\n// IsVisible indicates if the file tree view pane is currently initialized\nfunc (vm *FileTreeViewModel) IsVisible() bool {\n\treturn vm != nil\n}\n\n// ResetCursor moves the cursor back to the top of the buffer and translates to the top of the buffer.\nfunc (vm *FileTreeViewModel) ResetCursor() {\n\tvm.TreeIndex = 0\n\tvm.bufferIndex = 0\n\tvm.bufferIndexLowerBound = 0\n}\n\n// SetTreeByLayer populates the view model by stacking the indicated image layer file trees.\nfunc (vm *FileTreeViewModel) SetTreeByLayer(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int) error {\n\tif topTreeStop > len(vm.RefTrees)-1 {\n\t\treturn fmt.Errorf(\"invalid layer index given: %d of %d\", topTreeStop, len(vm.RefTrees)-1)\n\t}\n\tnewTree, err := vm.comparer.GetTree(filetree.NewTreeIndexKey(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to fetch layer tree from cache: %w\", err)\n\t}\n\n\t// preserve vm state on copy\n\tvisitor := func(node *filetree.FileNode) error {\n\t\tnewNode, err := newTree.GetNode(node.Path())\n\t\tif err == nil {\n\t\t\tnewNode.Data.ViewInfo = node.Data.ViewInfo\n\t\t}\n\t\treturn nil\n\t}\n\terr = vm.ModelTree.VisitDepthChildFirst(visitor, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to propagate layer tree: %w\", err)\n\t}","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/wagoodman/dive/blob/d6c691947f8fda635c952a17ee3b7555379d58f0/cmd/dive/cli/internal/ui/v1/viewmodel/filetree.go#L93-L129","documentation":"SetTreeByLayer guards the requested top-layer index against the number of analyzed layer trees (len(vm.RefTrees)-1) and rejects any index above the last valid one. The message shows 'requested of lastValidIndex'. It fires when the UI or CLI asks the filetree to display a layer that does not exist in the current image analysis.","triggerScenarios":"Calling SetTreeByLayer with topTreeStop > len(RefTrees)-1: selecting a layer index beyond the image's layer count (e.g. initial layer selection from config/CLI, or a listener passing a stale index after the image analysis changed), and edge cases with single-layer images where any index > 0 is invalid.","commonSituations":"Passing a layer index meant for a different image; scripts embedding the viewmodel that hardcode layer indexes; images with fewer layers than expected (single-stage scratch images); races where RefTrees is swapped while a layer selection is in flight.","solutions":["Clamp the requested index to len(RefTrees)-1 (or 0) before calling SetTreeByLayer","If selecting via UI, ensure the layer list view and the filetree viewmodel share the same RefTrees snapshot","Verify the image actually has that many layers: docker history <image> or dive's layer pane","For embedding code, pass initialLayer within bounds when constructing the viewmodel"],"exampleFix":"// before\nerr := vm.SetTreeByLayer(0, 0, requestedLayer, requestedLayer)\n// after\nif requestedLayer > len(vm.RefTrees)-1 {\n    requestedLayer = len(vm.RefTrees) - 1\n}\nerr := vm.SetTreeByLayer(0, 0, requestedLayer, requestedLayer)","handlingStrategy":"validation","validationCode":"// bounds-check before calling SetTreeByLayer\nmaxIdx := len(vm.RefTrees) - 1\nif topTreeStop > maxIdx { topTreeStop = maxIdx }\nif topTreeStart > maxIdx { topTreeStart = maxIdx }","typeGuard":null,"tryCatchPattern":"if err := vm.SetTreeByLayer(b0, b1, t0, t1); err != nil {\n    if strings.Contains(err.Error(), \"invalid layer index given\") {\n        // clamp and retry once\n        err = vm.SetTreeByLayer(b0, b1, len(vm.RefTrees)-1, len(vm.RefTrees)-1)\n    }\n    if err != nil { return err }\n}","preventionTips":["Always clamp UI-selected indexes to len(RefTrees)-1","Share one immutable RefTrees snapshot between views","Unit-test single-layer images (maxIdx == 0)"],"tags":["filetree","layer-index","bounds","validation"],"backgroundTag":null,"analyzedSha":"d6c691947f8fda635c952a17ee3b7555379d58f0","analyzedAt":"2026-08-15T09:42:35.293Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}