wagoodman/dive · warning
path does not exist: %s
Error message
path does not exist: %s
What it means
Returned (not panicked) by FileTree.GetNode (dive/filetree/file_tree.go:236). GetNode walks the children map segment by segment for a slash-delimited path; the moment a segment is missing from node.Children it returns 'path does not exist: %s'. It is the tree-walk equivalent of a failed map lookup.
Source
Thrown at dive/filetree/file_tree.go:236
failed = append(failed, NewPathError(node.Path(), ActionRemove, err))
}
}
return nil
}
stackErr = upper.VisitDepthChildFirst(graft, nil)
return failed, stackErr
}
// GetNode fetches a single node when given a slash-delimited string from root ('/') to the desired node (e.g. '/a/node/path')
func (tree *FileTree) GetNode(path string) (*FileNode, error) {
nodeNames := strings.Split(strings.Trim(path, "/"), "/")
node := tree.Root
for _, name := range nodeNames {
if name == "" {
continue
}
if node.Children[name] == nil {
return nil, fmt.Errorf("path does not exist: %s", path)
}
node = node.Children[name]
}
return node, nil
}
// AddPath adds a new node to the tree with the given payload
func (tree *FileTree) AddPath(filepath string, data FileInfo) (*FileNode, []*FileNode, error) {
filepath = path.Clean(filepath)
if filepath == "." {
return nil, nil, fmt.Errorf("cannot add relative path '%s'", filepath)
}
nodeNames := strings.Split(strings.Trim(filepath, "/"), "/")
node := tree.Root
addedNodes := make([]*FileNode, 0)
for idx, name := range nodeNames {
if name == "" {
continueView on GitHub (pinned to d6c691947f)
Solutions
- Check the path against the stacked/analysis tree, not an individual layer tree
- Normalize input first: path.Clean on the query, and remember segments are matched literally
- Handle the error as an expected 'not found' rather than a failure - this is a sentinel-style lookup miss
- Verify the path actually exists in the image: dive <image> then search for the file in the UI to confirm which tree holds it
Example fix
// before: assuming the node exists
node, _ := tree.GetNode("/etc/nginx/nginx.conf") // nil node + swallowed error -> later nil deref
// after: treat miss as a case
node, err := tree.GetNode(path.Clean(p))
if err != nil {
return fmt.Errorf("file not present in this tree: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// normalize before lookup
q := path.Clean(p)
if !strings.HasPrefix(q, "/") {
q = "/" + q
}
node, err := tree.GetNode(q)
if err != nil { /* expected miss */ } Try / catch
node, err := tree.GetNode(target)
if err != nil {
if strings.Contains(err.Error(), "path does not exist") {
// treat as not-found, not a failure
return nil, nil
}
return nil, fmt.Errorf("lookup %q: %w", target, err)
} Prevention
- Always path.Clean the query and force a leading '/'
- Query the stacked analysis tree, not per-layer trees, when checking for image files
- Treat GetNode's error as a sentinel 'not found' and handle it explicitly
When it happens
Trigger: Calling GetNode with a path whose first differing segment is absent - e.g. '/etc/nginx' when the tree has no 'etc' child; querying a path that only exists in a different (later) layer before those layers are stacked; typos or non-normalized input ('/etc//nginx' is tolerated by the empty-segment skip, but '/etc/./nginx' is not - '.' is looked up literally).
Common situations: Writing tooling on top of dive's filetree that probes for files by absolute path, then probing a path from a layer that was deleted (whiteout) or that was never added; querying the wrong tree object (per-layer tree instead of the stacked analysis tree).
Related errors
- cannot add relative path '%s'
- cannot open export file: %w
- file tree has path errors (use '--ignore-errors' to attempt
- notifyOnViewOptionChangeListeners error: %w
- unable to setup tree controller: %w
AI-assisted analysis of wagoodman/dive@d6c691947f (2026-08-15).
Data as JSON: /api/errors/601214265c2ac442.
Report an issue: GitHub.