docker/compose · error

newWatcher: %w

Error message

newWatcher: %w

What it means

On macOS the watcher is built on FSEvents; newWatcher converts each (already EncompassingPaths-merged) watch path to an absolute path before registering it with dw.initAdd. filepath.Abs fails only when the process working directory has been deleted or is unreadable, since Abs resolves relative paths against it. The error is wrapped with the newWatcher prefix to locate the failure site.

Source

Thrown at pkg/watch/watcher_darwin.go:136

func newWatcher(paths []string) (Notify, error) {
	dw := &fseventNotify{
		stream: &fsevents.EventStream{
			Latency: 50 * time.Millisecond,
			Flags:   fsevents.FileEvents | fsevents.IgnoreSelf,
			// NOTE(dmiller): this corresponds to the `sinceWhen` parameter in FSEventStreamCreate
			// https://developer.apple.com/documentation/coreservices/1443980-fseventstreamcreate
			EventID: fsevents.LatestEventID(),
		},
		events: make(chan FileEvent),
		errors: make(chan error),
		stop:   make(chan struct{}),
	}

	paths = pathutil.EncompassingPaths(paths)
	for _, path := range paths {
		path, err := filepath.Abs(path)
		if err != nil {
			return nil, fmt.Errorf("newWatcher: %w", err)
		}
		dw.initAdd(path)
	}

	return dw, nil
}

var _ Notify = &fseventNotify{}

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. cd into a directory that exists and rerun: `cd "$(pwd -P 2>/dev/null || echo $HOME)"` or just reopen your shell in the project root.
  2. Ensure clean/build steps never delete the shell's cwd — delete build outputs, not the directory containing them.
  3. Recreate the deleted directory if your workflow requires staying in it.
Defensive patterns

Strategy: validation

Validate before calling

// ensure cwd exists before constructing watchers
if wd, err := os.Getwd(); err != nil {
    return fmt.Errorf("working directory unavailable: %w", err)
} else if _, err := os.Stat(wd); err != nil {
    return fmt.Errorf("working directory %q no longer exists", wd)
}

Prevention

When it happens

Trigger: newWatcher(paths) on darwin where one of the EncompassingPaths results is relative and getwd() fails because the current working directory was removed (a common case: watching a directory that a build tool deleted, which happened to be the cwd).

Common situations: Running `docker compose watch` from a directory that a clean step (`make clean`, rm -rf dist) deleted; shell still sitting in a removed directory after a git clean; scripts cd-ing into temp dirs that another process purges.

Related errors


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