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 list

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Verify the wildcard's parent directory exists in the underlying FS before calling NewFilterFS with FollowPaths
  2. Check for case-sensitivity or separator mismatches in the FollowPaths pattern
  3. 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

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.