{"record":{"id":"b16a173ee19bf92d","repo":"wagoodman/dive","slug":"unable-to-propagate-vm-model-tree-w","errorCode":null,"errorMessage":"unable to propagate vm model tree: %w","messagePattern":"unable to propagate vm model tree: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cmd/dive/cli/internal/ui/v1/viewmodel/filetree.go","lineNumber":429,"sourceCode":"\terr := vm.ModelTree.VisitDepthChildFirst(func(node *filetree.FileNode) error {\n\t\tnode.Data.ViewInfo.Hidden = vm.HiddenDiffTypes[node.Data.DiffType]\n\t\tvisibleChild := false\n\t\tfor _, child := range node.Children {\n\t\t\tif !child.Data.ViewInfo.Hidden {\n\t\t\t\tvisibleChild = true\n\t\t\t\tnode.Data.ViewInfo.Hidden = false\n\t\t\t}\n\t\t}\n\t\t// hide nodes that do not match the current file filter regex (also don't unhide nodes that are already hidden)\n\t\tif filterRegex != nil && !visibleChild && !node.Data.ViewInfo.Hidden {\n\t\t\tmatch := filterRegex.FindString(node.Path())\n\t\t\tnode.Data.ViewInfo.Hidden = len(match) == 0\n\t\t}\n\t\treturn nil\n\t}, nil)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to propagate vm model tree: %w\", err)\n\t}\n\n\t// make a new tree with only visible nodes\n\tvm.ViewTree = vm.ModelTree.Copy()\n\terr = vm.ViewTree.VisitDepthParentFirst(func(node *filetree.FileNode) error {\n\t\tif node.Data.ViewInfo.Hidden {\n\t\t\terr1 := vm.ViewTree.RemovePath(node.Path())\n\t\t\tif err1 != nil {\n\t\t\t\treturn err1\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}, nil)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to propagate vm view tree: %w\", err)\n\t}\n","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/wagoodman/dive/blob/d6c691947f8fda635c952a17ee3b7555379d58f0/cmd/dive/cli/internal/ui/v1/viewmodel/filetree.go#L411-L447","documentation":"FileTreeViewModel.Update walks the model tree depth-child-first to recompute node visibility (diff-type hiding, parent-with-visible-child promotion, filter regex matching) and wraps traversal failures. The visitor returns nil on every path, so like the other propagation wraps this is defensive; the realistic way to see it is a fork adding fallible operations (e.g. RemovePath) into this visitor.","triggerScenarios":"ModelTree.VisitDepthChildFirst erroring during an Update call — triggered on every option toggle, filter edit, cursor move that calls Update, and layout changes; stock visitor cannot error.","commonSituations":"Stock dive: effectively unreachable. Forks that hide/prune nodes directly inside this visitor commonly introduce RemovePath-on-node-with-children errors that surface here.","solutions":["In stock dive, capture the chain and report upstream","In forks, move destructive pruning out of the visibility visitor (the codebase already prunes in a separate ViewTree pass)","Never mutate tree structure inside the visibility visitor; only set Hidden flags","Add tests exercising Update with filters + all diff types hidden to catch regressions"],"exampleFix":"// before (fork anti-pattern): removing inside the model-tree visitor\nerr := vm.ModelTree.VisitDepthChildFirst(func(n *filetree.FileNode) error {\n    if shouldHide(n) { return vm.ModelTree.RemovePath(n.Path()) } // can error\n    return nil\n}, nil)\n// after: only flag, prune later on the ViewTree copy\nerr := vm.ModelTree.VisitDepthChildFirst(func(n *filetree.FileNode) error {\n    n.Data.ViewInfo.Hidden = shouldHide(n)\n    return nil\n}, nil)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := vm.ModelTree.VisitDepthChildFirst(visibilityVisitor, nil); err != nil {\n    return fmt.Errorf(\"unable to propagate vm model tree: %w\", err)\n}","preventionTips":["Visibility visitors must only set flags, never mutate structure","Prune on a separate copy (ViewTree) as the codebase does","Write tests covering all-diff-types-hidden plus active filter"],"tags":["filetree","visibility","traversal","defensive"],"backgroundTag":null,"analyzedSha":"d6c691947f8fda635c952a17ee3b7555379d58f0","analyzedAt":"2026-08-15T09:42:35.293Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}