Skip to content

fix(tui): harden file-watcher against vanished-path ENOENT errors#796

Draft
posthog[bot] wants to merge 2 commits into
mainfrom
posthog-code/harden-file-watcher-enoent
Draft

fix(tui): harden file-watcher against vanished-path ENOENT errors#796
posthog[bot] wants to merge 2 commits into
mainfrom
posthog-code/harden-file-watcher-enoent

Conversation

@posthog

@posthog posthog Bot commented Jul 3, 2026

Copy link
Copy Markdown

Problem

The wizard's file-watcher hook (src/ui/tui/hooks/file-watcher.ts) raised unhandled ENOENT errors when the watched file's directory disappeared out from under its scheduled callbacks. startFileWatcher schedules three long-lived callbacks — a poll setInterval, an fs.watch change listener, and an attach-retry setInterval — each of which stats/accesses the watched path. The fs.watch watchers had no 'error' listener, so a watcher error on a vanished path surfaced as an uncaught exception, and already-scheduled callbacks could still fire after teardown.

This was recurring noise in the wizard's error tracking, firing entirely from the test suite (file-watcher.test.ts's afterEach removes the temp dir right after stop()) — no production/end-user impact, but it costs triage attention and masks real signals.

Why: to stop the recurring test/CI-only ENOENT noise in error tracking without changing watcher behavior.

Changes

  • Attach an 'error' handler to every fs.watch watcher so a vanished path can't raise an unhandled error event.
  • Add a stopped flag guarding read() and the attach-retry loop so callbacks scheduled before stop() become no-ops after teardown.
  • Guard w.close() in stop() against double-close.
  • Tighten the test teardown (stop + yield before removing the temp dir) and add a regression test covering the fs.watch error-event path.

Test plan

  • pnpm test — all 90 test files / 1157 tests pass, including the new regression test.
  • The new test deterministically fails on the pre-fix code (the emitted 'error' event throws with no listener) and passes with the fix.
  • pnpm build and lint (eslint) clean.

Created with PostHog Code from an inbox report.

startFileWatcher schedules three long-lived callbacks (poll setInterval,
fs.watch change listener, attach-retry setInterval) that stat/access the
watched path. When the path's directory disappears out from under them, the
fs.watch watchers had no 'error' listener, so a watcher error surfaced as an
uncaught ENOENT, and already-scheduled callbacks could run after teardown.

- Attach an 'error' handler to every fs.watch watcher (via attachWatch) so a
  vanished path can't raise an unhandled error event.
- Add a stopped flag guarding read() and the attach-retry loop so callbacks
  scheduled before stop() become no-ops after teardown.
- Guard w.close() in stop() against double-close.
- Tighten the test teardown to stop the watcher and yield before removing the
  temp dir, and add a regression test for the fs.watch error-event path.

Generated-By: PostHog Code
Task-Id: 2a9a5b2b-5927-4eab-8fa9-af9c7fae3e57
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci basic-integration
  • /wizard-ci error-tracking-upload-source-maps
  • /wizard-ci mcp-analytics
  • /wizard-ci misc
  • /wizard-ci revenue

Test an individual app:

  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
Show more apps
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /wizard-ci basic-integration/javascript-node
  • /wizard-ci basic-integration/javascript-web
  • /wizard-ci basic-integration/laravel
  • /wizard-ci basic-integration/next-js
  • /wizard-ci basic-integration/nuxt
  • /wizard-ci basic-integration/python
  • /wizard-ci basic-integration/rails
  • /wizard-ci basic-integration/react-native
  • /wizard-ci basic-integration/react-router
  • /wizard-ci basic-integration/sveltekit
  • /wizard-ci basic-integration/swift
  • /wizard-ci basic-integration/tanstack-router
  • /wizard-ci basic-integration/tanstack-start
  • /wizard-ci basic-integration/vue
  • /wizard-ci error-tracking-upload-source-maps/android
  • /wizard-ci error-tracking-upload-source-maps/cicd-docker-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-github-actions-docker-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-github-actions-nested-docker-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-github-actions-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-github-actions-single-stage-docker-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-gitlab-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-monorepo-pnpm-node-react
  • /wizard-ci error-tracking-upload-source-maps/cicd-monorepo-raw-node-react
  • /wizard-ci error-tracking-upload-source-maps/cicd-ssh-vps-node-raw
  • /wizard-ci error-tracking-upload-source-maps/flutter
  • /wizard-ci error-tracking-upload-source-maps/ios
  • /wizard-ci error-tracking-upload-source-maps/next
  • /wizard-ci error-tracking-upload-source-maps/next-no-posthog
  • /wizard-ci error-tracking-upload-source-maps/node-raw
  • /wizard-ci error-tracking-upload-source-maps/node-rollup
  • /wizard-ci error-tracking-upload-source-maps/node-rollup-typescript-plugin
  • /wizard-ci error-tracking-upload-source-maps/node-webpack
  • /wizard-ci error-tracking-upload-source-maps/nuxt-3-6
  • /wizard-ci error-tracking-upload-source-maps/nuxt-4-3
  • /wizard-ci error-tracking-upload-source-maps/react-native
  • /wizard-ci error-tracking-upload-source-maps/react-vite
  • /wizard-ci error-tracking-upload-source-maps/rust
  • /wizard-ci mcp-analytics/custom-dispatcher
  • /wizard-ci mcp-analytics/typescript-sdk
  • /wizard-ci misc/quack-quack
  • /wizard-ci revenue/stripe

Results will be posted here when complete.

Generated-By: PostHog Code
Task-Id: 2a9a5b2b-5927-4eab-8fa9-af9c7fae3e57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants