microsoft/typescript-go · error

CreateEvent: %w

Error message

CreateEvent: %w

What it means

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.

Source

Thrown at internal/fswatch/windows.go:212

		stopCh:   make(chan struct{}),
		doneCh:   make(chan struct{}),
		bufBytes: defaultBufSize,
	}, nil
}

func (s *windowsSubscription) beginRead() (*windowsRead, error) {
	s.mu.Lock()
	if s.stopped {
		s.mu.Unlock()
		return nil, nil
	}
	bufSize := s.bufBytes
	s.mu.Unlock()

	req := &windowsRead{buf: make([]byte, bufSize)}
	ev, err := windows.CreateEvent(nil, 1, 0, nil)
	if err != nil {
		return nil, fmt.Errorf("CreateEvent: %w", err)
	}
	req.event = ev
	req.overlapped.HEvent = ev

	var bytesReturned uint32
	err = windows.ReadDirectoryChanges(
		s.handle,
		&req.buf[0],
		uint32(len(req.buf)),
		s.dirWatch.recursive, // recursive
		notifyChangeFilter,
		&bytesReturned,
		&req.overlapped,
		0,
	)
	if err != nil {
		_ = windows.CloseHandle(ev)
		return nil, &dirWatchError{err: errReadChanges, dirWatch: s.dirWatch}

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Reduce simultaneous watches: consolidate sibling directories into one recursive WithRecursive watch
  2. Find and fix handle leaks in the process (watch handle count in Task Manager or Process Explorer)
  3. Retry with backoff: transient exhaustion clears as other handles close
  4. If delivered as ErrWatchTerminated, call Close() and re-subscribe after freeing handles
Defensive patterns

Strategy: retry

Validate before calling

// Cap concurrent watches; consolidate where possible:
// one recursive watch instead of N per-child watches
if activeWatches >= maxWatches {
    return errors.New("watch budget exceeded")
}

Try / catch

// subscribe-time:
if err != nil && strings.Contains(err.Error(), "CreateEvent") {
    // kernel object exhaustion: close idle handles, then retry with backoff
}
// run-time (via callback):
if errors.Is(err, fswatch.ErrWatchTerminated) {
    watch.Close()
    go resubscribeAfterFreedHandles(dir)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/08e1e6533d032216. Report an issue: GitHub.