docker/compose · error

os.Stat(%q): %w

Error message

os.Stat(%q): %w

What it means

While walking a watch path upward, greatestExistingAncestor stats each candidate. os.Stat returning an error that is NOT os.IsNotExist (for example EACCES on a parent directory, or EIO) cannot be handled by the climb-up logic, so it is wrapped with the offending path for diagnosis. This is a hard environment error, distinct from the expected not-yet-existing path case.

Source

Thrown at pkg/watch/paths.go:33

*/

package watch

import (
	"fmt"
	"os"
	"path/filepath"
)

func greatestExistingAncestor(path string) (string, error) {
	if path == string(filepath.Separator) ||
		path == fmt.Sprintf("%s%s", filepath.VolumeName(path), string(filepath.Separator)) {
		return "", fmt.Errorf("cannot watch root directory")
	}

	_, err := os.Stat(path)
	if err != nil && !os.IsNotExist(err) {
		return "", fmt.Errorf("os.Stat(%q): %w", path, err)
	}

	if os.IsNotExist(err) {
		return greatestExistingAncestor(filepath.Dir(path))
	}

	return path, nil
}

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Check the exact path in the message: `ls -ld <path>` and fix ownership/permissions (chmod +x the ancestor, or run as a user with search rights).
  2. If the path is on a network/FUSE mount, verify the mount is healthy (`mount | grep <path>`, dmesg) and remount if needed.
  3. Repoint the watch path to a location whose full ancestor chain is accessible.

Example fix

# before: ancestor not traversable
ls -ld /home/otheruser   # drwx------ otheruser
# after
sudo chmod o+x /home/otheruser   # or move the project under your own home
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check the full ancestor chain is traversable
for dir := path; ; dir = filepath.Dir(dir) {
    if _, err := os.Stat(dir); err != nil && !os.IsNotExist(err) {
        return fmt.Errorf("cannot stat %q: %w", dir, err)
    }
    if dir == filepath.Dir(dir) { break }
}

Try / catch

if err != nil {
    var pathErr *os.PathError
    if errors.As(err, &pathErr) && os.IsPermission(pathErr) {
        // surface a permission-specific hint with the path from pathErr.Path
    }
    return err
}

Prevention

When it happens

Trigger: A parent directory in the path chain denying search permission to the current user (stat fails with permission denied), or a filesystem-level I/O error. Triggered during path normalization for the watch subsystem.

Common situations: Home-directory paths where an ancestor is mode 000 or owned by another user; NFS/FUSE mounts in a bad state returning EIO; SELinux/AppArmor denying stat; running compose watch over paths inside a broken VM share.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/9ab9c169d8b2a50c. Report an issue: GitHub.