{"record":{"id":"08e1e6533d032216","repo":"microsoft/typescript-go","slug":"createevent-w","errorCode":null,"errorMessage":"CreateEvent: %w","messagePattern":"CreateEvent: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/fswatch/windows.go","lineNumber":212,"sourceCode":"\t\tstopCh:   make(chan struct{}),\n\t\tdoneCh:   make(chan struct{}),\n\t\tbufBytes: defaultBufSize,\n\t}, nil\n}\n\nfunc (s *windowsSubscription) beginRead() (*windowsRead, error) {\n\ts.mu.Lock()\n\tif s.stopped {\n\t\ts.mu.Unlock()\n\t\treturn nil, nil\n\t}\n\tbufSize := s.bufBytes\n\ts.mu.Unlock()\n\n\treq := &windowsRead{buf: make([]byte, bufSize)}\n\tev, err := windows.CreateEvent(nil, 1, 0, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"CreateEvent: %w\", err)\n\t}\n\treq.event = ev\n\treq.overlapped.HEvent = ev\n\n\tvar bytesReturned uint32\n\terr = windows.ReadDirectoryChanges(\n\t\ts.handle,\n\t\t&req.buf[0],\n\t\tuint32(len(req.buf)),\n\t\ts.dirWatch.recursive, // recursive\n\t\tnotifyChangeFilter,\n\t\t&bytesReturned,\n\t\t&req.overlapped,\n\t\t0,\n\t)\n\tif err != nil {\n\t\t_ = windows.CloseHandle(ev)\n\t\treturn nil, &dirWatchError{err: errReadChanges, dirWatch: s.dirWatch}","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/fswatch/windows.go#L194-L230","documentation":"Error raised when CreateEvent fails while arming an overlapped ReadDirectoryChangesW request in beginRead; the %w wraps the Win32 error. On the first read (inside subscribe) it fails WatchDirectory synchronously; failures for later reads go through fatal() and reach the callback wrapped with ErrWatchTerminated. CreateEvent allocates a kernel event object, so failure in practice means kernel object or memory exhaustion.","triggerScenarios":"Process or system handle limits reached: thousands of concurrent watches each create event objects, or other code in the process leaks handles. Paged pool exhaustion under heavy pressure.","commonSituations":"Servers watching thousands of directories with one subscription each. Programs leaking handles over long uptimes until CreateEvent fails. Watch churn that outpaces kernel object cleanup.","solutions":["Reduce simultaneous watches: consolidate sibling directories into one recursive WithRecursive watch","Find and fix handle leaks in the process (watch handle count in Task Manager or Process Explorer)","Retry with backoff: transient exhaustion clears as other handles close","If delivered as ErrWatchTerminated, call Close() and re-subscribe after freeing handles"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Cap concurrent watches; consolidate where possible:\n// one recursive watch instead of N per-child watches\nif activeWatches >= maxWatches {\n    return errors.New(\"watch budget exceeded\")\n}","typeGuard":null,"tryCatchPattern":"// subscribe-time:\nif err != nil && strings.Contains(err.Error(), \"CreateEvent\") {\n    // kernel object exhaustion: close idle handles, then retry with backoff\n}\n// run-time (via callback):\nif errors.Is(err, fswatch.ErrWatchTerminated) {\n    watch.Close()\n    go resubscribeAfterFreedHandles(dir)\n}","preventionTips":["Track handle count in long-running processes; leak-detector alerts before CreateEvent fails","Consolidate sibling watches into recursive watches to cut kernel objects","Retry with backoff: transient exhaustion clears when handles close","Close watches as soon as they are no longer needed"],"tags":["windows","resource-limits","kernel-objects","overlapped-io"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}