dagger/dagger · warning
readFile %s
Error message
readFile %s
What it means
statFile returns os.ErrNotExist wrapped as "readFile %s" when its walk over the FS completed without producing any entry for the root. This is the not-found signal that readSymlink translates into 'no symlink here' (returns nil targets), so callers usually see the path treated as absent.
Source
Thrown at internal/fsutil/followlinks.go:163
err := fs.Walk(context.TODO(), root, func(p string, entry os.DirEntry, err error) error {
if err != nil {
return err
}
if p != root {
return errors.Errorf("expected single entry %q but got %q", root, p)
}
out = entry
if entry.IsDir() {
return filepath.SkipDir
}
return nil
})
if err != nil {
return nil, err
}
if out == nil {
return nil, errors.Wrapf(os.ErrNotExist, "readFile %s", root)
}
return out, nil
}
func readDir(fs FS, root string) ([]os.DirEntry, error) {
var out []os.DirEntry
root = filepath.FromSlash(filepath.Clean(root))
if root == string(filepath.Separator) || root == "." {
root = "."
out = make([]gofs.DirEntry, 0)
}
err := fs.Walk(context.TODO(), root, func(p string, entry os.DirEntry, err error) error {
if err != nil {
return err
}
if p == root {View on GitHub (pinned to 82ba2681db)
Solutions
- Confirm each FollowPaths entry exists in the FS at NewFilterFS time; remove stale entries
- Avoid following the FS root itself; FollowLinks paths like "/" or "." short-circuit and resolve to nothing meaningful
- Handle not-found gracefully in callers — readSymlink already swallows isNotFound, so surface only if it escapes via a different wrap
Example fix
// before
FollowPaths: []string{"bin/dagger"} // missing in snapshot
// after
// ensure bin/dagger exists in the FS before NewFilterFS, or drop it from FollowPaths Defensive patterns
Strategy: validation
Validate before calling
// Confirm each FollowPaths entry exists before NewFilterFS
for _, p := range opt.FollowPaths {
if _, err := underlying.Open(filepath.Clean(p)); err != nil {
return fmt.Errorf("FollowPaths entry missing: %s", p)
}
} Try / catch
targets, err := fsutil.FollowLinks(fs, paths)
if err != nil {
if errors.Is(err, os.ErrNotExist) { return nil, nil } // absent link: no targets
return err
} Prevention
- Build FollowPaths from paths verified to exist in the snapshot
- Watch for '/' or '.' entries which short-circuit to no entry
- Re-check symlink existence after snapshot/copy operations
When it happens
Trigger: FollowLinks/NewFilterFS resolving a FollowPaths entry (or wildcard match) where statFile's walk finds nothing — the path doesn't exist in the underlying FS snapshot, or the root is "/" or "." which short-circuits to nil entry and then ErrNotExist.
Common situations: FollowPaths listing a symlink that was deleted or never existed in the snapshot, a typo in the followed path, or a wildcard that matched names (via readDir) pointing at paths absent from the 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/711503c9f3ceb3c5.
Report an issue: GitHub.