wagoodman/dive · error

unknown diff.hide value: %s

Error message

unknown diff.hide value: %s

What it means

NewFileTreeViewModel validates the diff.hide preference entries (case-insensitive) against the fixed set added/removed/modified/unmodified and rejects anything else at startup. This is a pure config-validation error: the value shown is the lowercased offending token from your dive.yaml (or CLI --diff.hide flag), so the app refuses to start the TUI.

Source

Thrown at cmd/dive/cli/internal/ui/v1/viewmodel/filetree.go:70

	treeViewModel.CollapseAll = cfg.Preferences.CollapseFiletreeDirectory
	treeViewModel.ModelTree = cfg.Analysis.RefTrees[initialLayer]
	treeViewModel.RefTrees = cfg.Analysis.RefTrees
	treeViewModel.comparer = comparer
	treeViewModel.HiddenDiffTypes = make([]bool, 4)

	hiddenTypes := cfg.Preferences.FiletreeDiffHide
	for _, hType := range hiddenTypes {
		switch t := strings.ToLower(hType); t {
		case "added":
			treeViewModel.HiddenDiffTypes[filetree.Added] = true
		case "removed":
			treeViewModel.HiddenDiffTypes[filetree.Removed] = true
		case "modified":
			treeViewModel.HiddenDiffTypes[filetree.Modified] = true
		case "unmodified":
			treeViewModel.HiddenDiffTypes[filetree.Unmodified] = true
		default:
			return nil, fmt.Errorf("unknown diff.hide value: %s", t)
		}
	}

	return treeViewModel, treeViewModel.SetTreeByLayer(0, 0, initialLayer, initialLayer)
}

// Setup initializes the UI concerns within the context of a global [gocui] view object.
func (vm *FileTreeViewModel) Setup(lowerBound, height int) {
	vm.bufferIndexLowerBound = lowerBound
	vm.refHeight = height
}

// height returns the current height and considers the header
func (vm *FileTreeViewModel) height() int {
	if vm.ShowAttributes {
		return vm.refHeight - 1
	}
	return vm.refHeight

View on GitHub (pinned to d6c691947f)

Solutions

  1. Edit dive.yaml and set diff.hide entries to only: added, removed, modified, or unmodified (any capitalization)
  2. Remove the diff.hide key entirely if you don't want to hide any diff types
  3. If using the CLI flag, correct it: --diff.hide=modified or a comma list of valid values
  4. Validate config after editing: run dive with a trivial image to confirm startup

Example fix

# before (dive.yaml)
diff:
  hide:
    - changed
    - new
# after
diff:
  hide:
    - modified
    - added
Defensive patterns

Strategy: validation

Validate before calling

// validate diff.hide entries before constructing the viewmodel
valid := map[string]bool{"added": true, "removed": true, "modified": true, "unmodified": true}
for _, v := range cfg.Preferences.FiletreeDiffHide {
    if !valid[strings.ToLower(v)] {
        return fmt.Errorf("invalid diff.hide %q (want added|removed|modified|unmodified)", v)
    }
}

Type guard

// simple set-membership check for config values
func isValidDiffHide(s string) bool {
    switch strings.ToLower(s) {
    case "added", "removed", "modified", "unmodified":
        return true
    }
    return false
}

Try / catch

vm, err := viewmodel.NewFileTreeViewModel(cfg, initialLayer)
if err != nil {
    if strings.Contains(err.Error(), "unknown diff.hide value") {
        // fix config and restart
    }
}

Prevention

When it happens

Trigger: Setting FiletreeDiffHide / diff.hide in dive.yaml or via CLI to any string outside {added, removed, modified, unmodified} (case-insensitive), e.g. 'changed', 'add', 'Modified ' with a typo, or a YAML list entry that parses to a non-string.

Common situations: Hand-edited dive.yaml with intuitive-but-wrong names like 'changed', 'new', 'deleted'; copy-pasted configs from older dive versions or blog posts; YAML indentation mistakes turning the list into a single garbled string; CLI flag --diff.hide=changed.

Related errors


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