pulumi/pulumi · error
failed to watch file: %w
Error message
failed to watch file: %w
What it means
This error wraps a failure from watchFile, which tails the engine's eventlog file (logdir/eventlog.txt) so that registered event receivers can consume deployment events in watch mode. It is thrown when the underlying file watcher cannot be created — typically because the log file does not exist, cannot be opened, or the polling/fsnotify watcher fails to initialize. It is a setup failure, not a deployment failure; no events have been processed yet.
Source
Thrown at sdk/go/auto/stack.go:1968
logDir := filepath.Dir(fw.tail.Filename)
fw.tail.Cleanup()
os.RemoveAll(logDir)
// set to nil so we can safely close again in defer
fw.tail = nil
}
func tailLogs(command string, receivers []chan<- events.EngineEvent, version semver.Version) (Watcher, error) {
if version.LTE(semver.Version{Major: 3, Minor: 205}) {
logDir, err := os.MkdirTemp("", fmt.Sprintf("automation-logs-%s-", command))
if err != nil {
return nil, fmt.Errorf("failed to create logdir: %w", err)
}
logFile := filepath.Join(logDir, "eventlog.txt")
t, err := watchFile(logFile, receivers)
if err != nil {
return nil, fmt.Errorf("failed to watch file: %w", err)
}
return t, nil
} else {
host := newEventsServer(receivers)
cancel := make(chan bool)
handle, err := rpcutil.ServeWithOptions(rpcutil.ServeOptions{
Init: func(srv *grpc.Server) error {
pulumirpc.RegisterEventsServer(srv, host)
return nil
},
Cancel: cancel,
Options: rpcutil.TracingServerInterceptorOptions(nil),
})
if err != nil {
return nil, err
}
return &eventsWatcher{View on GitHub (pinned to 793f7b2e16)
Solutions
- Check that the log directory (PULUMI_DEBUG_GRPC... / logdir path) is writable by the process user and that the eventlog.txt file exists before watching
- Retry the watch call — the log file may not have been flushed/created yet at watch time
- Ensure only one watcher is started per stack run to avoid races on the logdir
- Inspect the wrapped error (%w) for the root cause: open failure, permission denied, or watcher init error
Example fix
// before
t, err := stack.Watch(ctx)
if err != nil { return err }
// after
t, err := stack.Watch(ctx)
if err != nil {
if os.IsPermission(errors.Unwrap(err)) {
// fix logdir permissions or choose another log dir
}
return fmt.Errorf("watch setup failed: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := os.Stat(filepath.Join(logDir, "eventlog.txt")); err != nil {
return fmt.Errorf("eventlog not available: %w", err)
} Try / catch
t, err := stack.Watch(ctx)
if err != nil {
var perr *fs.PathError
if errors.As(err, &perr) {
// handle missing/unreadable eventlog before retrying
}
return err
} Prevention
- Ensure the log directory is writable by the process user (especially in containers)
- Start only one watcher per stack run to avoid logdir races
- Retry the watch briefly — the log file may not exist at first attempt
When it happens
Trigger: Calling Watch/WatchAsync on an automation API Stack with Debugging or EventLog watchers enabled, when watchFile(logFile, receivers) fails — e.g. the eventlog file was not created because logDir creation succeeded but the watcher cannot open the file (permissions, file deleted concurrently, invalid logdir path).
Common situations: Running Pulumi operations in restricted sandboxes/containers where /tmp or the logdir is read-only; antivirus or log rotation deleting the eventlog file mid-setup; disk full preventing the log file from being created; concurrent Watch calls racing on the same stack's logdir.
Related errors
- failed to run `pulumi version`: %w
- unable to read config: %w
- unable to unmarshal config value: %w
- unable to set config: %w
- unable to set config from JSON: %w
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/cfa1e04127e30882.
Report an issue: GitHub.