docker/compose · error

walking %q: %w

Error message

walking %q: %w

What it means

entriesForPath enumerates a synced directory recursively with filepath.Walk. Any error the walk itself reports (unreadable directory during readdir, permission denied descending) is wrapped as 'walking %q' for the current path. It is the directory-traversal analogue of the stat errors.

Source

Thrown at internal/sync/tar.go:272

			return nil, nil
		}
		return nil, err
	}

	localPathIsDir := localInfo.IsDir()
	if localPathIsDir {
		// Make sure we can trim this off filenames to get valid relative filepaths
		if !strings.HasSuffix(localPath, string(filepath.Separator)) {
			localPath += string(filepath.Separator)
		}
	}

	containerPath = strings.TrimPrefix(containerPath, "/")

	result := make([]archiveEntry, 0)
	err = filepath.Walk(localPath, func(curLocalPath string, info os.FileInfo, err error) error {
		if err != nil {
			return fmt.Errorf("walking %q: %w", curLocalPath, err)
		}

		linkname := ""
		if info.Mode()&os.ModeSymlink != 0 {
			var err error
			linkname, err = os.Readlink(curLocalPath)
			if err != nil {
				return err
			}
		}

		var name string
		//nolint:gocritic
		if localPathIsDir {
			// Name of file in tar should be relative to source directory...
			tmp, err := filepath.Rel(localPath, curLocalPath)
			if err != nil {
				return fmt.Errorf("making %q relative to %q: %w", curLocalPath, localPath, err)

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Grant read+traverse on the failing subdirectory: chmod u+rX (the message names curLocalPath exactly)
  2. Exclude unreadable subtrees from the PathMapping (e.g. do not sync .git or root-owned build outputs)
  3. If the directory was transiently removed, simply retry the sync — the fresh walk will not see it
  4. Repair/remount faulty network filesystems before syncing

Example fix

# the error names the exact unreadable path
ls '/path/from/error'   # -> Permission denied
chmod u+rX '/path/from/error'
Defensive patterns

Strategy: validation

Validate before calling

// pre-walk the sync root with the compose user; fail fast on unreadable dirs
err := filepath.Walk(root, func(p string, fi os.FileInfo, err error) error {
    if err != nil { return err }
    if fi.IsDir() && fi.Mode()&0500 != 0500 { return fmt.Errorf("not readable/traversable: %s", p) }
    return nil
})

Try / catch

// extract curLocalPath from the wrap, chmod it, re-run Sync

Prevention

When it happens

Trigger: filepath.Walk's callback receiving a non-nil err: a subdirectory without read/execute permission for the compose process, a directory removed between listing and descent, or EIO from the filesystem during readdir.

Common situations: Sync roots containing root-owned directories (created by an earlier privileged container) that an unprivileged compose run cannot enumerate; node_modules with restrictive modes; flaky NFS mounts.

Related errors


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