dagger/dagger · warning
readDir %s
Error message
readDir %s
What it means
readDir wraps os.ErrNotExist as "readDir %s" when the walk produced no entries at all and the root isn't ".". It means the directory being listed (to expand a wildcard in FollowPaths) does not exist in the FS snapshot; readSymlink treats this as not-found and resolves no targets.
Source
Thrown at internal/fsutil/followlinks.go:202
}
out = make([]gofs.DirEntry, 0)
return nil
}
if out == nil {
return errors.Errorf("expected to read parent entry %q before child %q", root, p)
}
out = append(out, entry)
if entry.IsDir() {
return filepath.SkipDir
}
return nil
})
if err != nil {
return nil, err
}
if out == nil && root != "." {
return nil, errors.Wrapf(os.ErrNotExist, "readDir %s", root)
}
return out, nil
}
func containsWildcards(name string) bool {
isWindows := runtime.GOOS == "windows"
for i := 0; i < len(name); i++ {
ch := name[i]
if ch == '\\' && !isWindows {
i++
} else if ch == '*' || ch == '?' || ch == '[' {
return true
}
}
return false
}
// dedupePaths expects input as a sorted listView on GitHub (pinned to 82ba2681db)
Solutions
- Verify the wildcard's parent directory exists in the underlying FS before calling NewFilterFS with FollowPaths
- Check for case-sensitivity or separator mismatches in the FollowPaths pattern
- Treat nil resolved targets as expected: readSymlink swallows not-found, so only handle this if the wrapped error escapes another path
Example fix
// before
FollowPaths: []string{"output/*.json"} // output/ missing
// after
// create/verify output/ in the FS snapshot first, or FollowPaths: []string{} Defensive patterns
Strategy: validation
Validate before calling
// Verify the wildcard's parent directory exists before resolving links
parent := filepath.Dir(pattern)
if _, err := underlying.Open(parent); err != nil {
return fmt.Errorf("wildcard parent missing: %s", parent)
} Try / catch
targets, err := fsutil.FollowLinks(fs, paths)
if err != nil {
if errors.Is(err, os.ErrNotExist) { return nil, nil } // dir absent: no matches
return err
} Prevention
- Check case-sensitivity of directory names in FollowPaths patterns
- Ensure directories are materialized in the snapshot before link resolution
- Remember absent dirs resolve to zero targets, not a hard failure, in readSymlink
When it happens
Trigger: FollowLinks/NewFilterFS with a wildcard FollowPaths entry ("glob/*") whose parent directory is missing — readDir's walk finds no root entry, out stays nil, and ErrNotExist is wrapped.
Common situations: Wildcards pointing into directories absent from the snapshot (deleted build output, case-mismatched directory names, paths excluded by an outer filter FS), or following links before the directory is created in a lazy FS.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/229b65d91a606c38.
Report an issue: GitHub.