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

  1. In stock dive, capture the chain and report upstream
  2. In forks, move destructive pruning out of the visibility visitor (the codebase already prunes in a separate ViewTree pass)
  3. Never mutate tree structure inside the visibility visitor; only set Hidden flags
  4. 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

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


AI-assisted analysis of wagoodman/dive@d6c691947f (2026-08-15). Data as JSON: /api/errors/b16a173ee19bf92d. Report an issue: GitHub.