{"record":{"id":"cfa1e04127e30882","repo":"pulumi/pulumi","slug":"failed-to-watch-file-w","errorCode":null,"errorMessage":"failed to watch file: %w","messagePattern":"failed to watch file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdk/go/auto/stack.go","lineNumber":1968,"sourceCode":"\tlogDir := filepath.Dir(fw.tail.Filename)\n\tfw.tail.Cleanup()\n\tos.RemoveAll(logDir)\n\n\t// set to nil so we can safely close again in defer\n\tfw.tail = nil\n}\n\nfunc tailLogs(command string, receivers []chan<- events.EngineEvent, version semver.Version) (Watcher, error) {\n\tif version.LTE(semver.Version{Major: 3, Minor: 205}) {\n\t\tlogDir, err := os.MkdirTemp(\"\", fmt.Sprintf(\"automation-logs-%s-\", command))\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to create logdir: %w\", err)\n\t\t}\n\t\tlogFile := filepath.Join(logDir, \"eventlog.txt\")\n\n\t\tt, err := watchFile(logFile, receivers)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to watch file: %w\", err)\n\t\t}\n\n\t\treturn t, nil\n\t} else {\n\t\thost := newEventsServer(receivers)\n\t\tcancel := make(chan bool)\n\t\thandle, err := rpcutil.ServeWithOptions(rpcutil.ServeOptions{\n\t\t\tInit: func(srv *grpc.Server) error {\n\t\t\t\tpulumirpc.RegisterEventsServer(srv, host)\n\t\t\t\treturn nil\n\t\t\t},\n\t\t\tCancel:  cancel,\n\t\t\tOptions: rpcutil.TracingServerInterceptorOptions(nil),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &eventsWatcher{","sourceCodeStart":1950,"sourceCodeEnd":1986,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/sdk/go/auto/stack.go#L1950-L1986","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nt, err := stack.Watch(ctx)\nif err != nil { return err }\n\n// after\nt, err := stack.Watch(ctx)\nif err != nil {\n    if os.IsPermission(errors.Unwrap(err)) {\n        // fix logdir permissions or choose another log dir\n    }\n    return fmt.Errorf(\"watch setup failed: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"if _, err := os.Stat(filepath.Join(logDir, \"eventlog.txt\")); err != nil {\n    return fmt.Errorf(\"eventlog not available: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"t, err := stack.Watch(ctx)\nif err != nil {\n    var perr *fs.PathError\n    if errors.As(err, &perr) {\n        // handle missing/unreadable eventlog before retrying\n    }\n    return err\n}","preventionTips":["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"],"tags":["go","automation-api","file-watching","eventlog"],"backgroundTag":"file-watch-setup-failed","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}