wagoodman/dive · warning
unable to propagate vm model tree: %w
Error message
unable to propagate vm model tree: %w
What it means
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.
Source
Thrown at cmd/dive/cli/internal/ui/v1/viewmodel/filetree.go:429
err := vm.ModelTree.VisitDepthChildFirst(func(node *filetree.FileNode) error {
node.Data.ViewInfo.Hidden = vm.HiddenDiffTypes[node.Data.DiffType]
visibleChild := false
for _, child := range node.Children {
if !child.Data.ViewInfo.Hidden {
visibleChild = true
node.Data.ViewInfo.Hidden = false
}
}
// hide nodes that do not match the current file filter regex (also don't unhide nodes that are already hidden)
if filterRegex != nil && !visibleChild && !node.Data.ViewInfo.Hidden {
match := filterRegex.FindString(node.Path())
node.Data.ViewInfo.Hidden = len(match) == 0
}
return nil
}, nil)
if err != nil {
return fmt.Errorf("unable to propagate vm model tree: %w", err)
}
// make a new tree with only visible nodes
vm.ViewTree = vm.ModelTree.Copy()
err = vm.ViewTree.VisitDepthParentFirst(func(node *filetree.FileNode) error {
if node.Data.ViewInfo.Hidden {
err1 := vm.ViewTree.RemovePath(node.Path())
if err1 != nil {
return err1
}
}
return nil
}, nil)
if err != nil {
return fmt.Errorf("unable to propagate vm view tree: %w", err)
}
View on GitHub (pinned to d6c691947f)
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
Example fix
// before (fork anti-pattern): removing inside the model-tree visitor
err := vm.ModelTree.VisitDepthChildFirst(func(n *filetree.FileNode) error {
if shouldHide(n) { return vm.ModelTree.RemovePath(n.Path()) } // can error
return nil
}, nil)
// after: only flag, prune later on the ViewTree copy
err := vm.ModelTree.VisitDepthChildFirst(func(n *filetree.FileNode) error {
n.Data.ViewInfo.Hidden = shouldHide(n)
return nil
}, nil) Defensive patterns
Strategy: try-catch
Try / catch
if err := vm.ModelTree.VisitDepthChildFirst(visibilityVisitor, nil); err != nil {
return fmt.Errorf("unable to propagate vm model tree: %w", err)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Stock dive: effectively unreachable. Forks that hide/prune nodes directly inside this visitor commonly introduce RemovePath-on-node-with-children errors that surface here.
Related errors
- unable to propagate layer tree: %w
- unable to propagate tree on cursorLeft: %w
- unable to propagate vm view tree: %w
- file tree has path errors (use '--ignore-errors' to attempt
- unable to setup debug controller: %w
AI-assisted analysis of wagoodman/dive@d6c691947f (2026-08-15).
Data as JSON: /api/errors/b16a173ee19bf92d.
Report an issue: GitHub.