abhigyanpatwari/GitNexus · error · WatchControlReloadError

Unable to re-arm the filesystem watcher

Error message

Unable to re-arm the filesystem watcher

What it means

rearmWatcher() replaces the fs watcher when re-arming is pending. If creating/starting the replacement watcher itself throws, it closes the half-built replacement and throws a WatchControlReloadError with 'Unable to re-arm the filesystem watcher', with the original error as cause. Watch mode cannot continue without a live watcher.

Source

Thrown at gitnexus/src/cli/analyze-watch.ts:367

  // rescan would emit, an immediate rewrite of that file is dropped for good
  // (reproduced on chokidar 4 and 5). So re-arm by arming a replacement
  // watcher and awaiting its `ready` instead. The outgoing instance keeps
  // reporting until the replacement is armed, so the swap has no blind window,
  // and a replacement that fails to arm leaves the working instance in place.
  const rearmWatcher = async (): Promise<void> => {
    rearmPending = false;
    if (closed) return;
    const replacement = createWatcher();
    try {
      await waitUntilReady(replacement);
    } catch (error) {
      rearmPending = true;
      try {
        await replacement.close();
      } catch {
        // The instance never became live; the arm error is the one to report.
      }
      throw new WatchControlReloadError(
        new Error('Unable to re-arm the filesystem watcher', { cause: error }),
      );
    }
    const retired = watcher;
    watcher = replacement;
    await retired.close();
    // `close()` can land between arming the replacement and the swap above.
    if (closed) await replacement.close();
  };

  try {
    await waitUntilReady(watcher);
    await queue.runInitial();
  } catch (error) {
    closed = true;
    await watcher.close();
    await queue.close();
    throw error;

View on GitHub (pinned to 0d1aed942f)

Solutions

  1. Restart `gitnexus analyze --watch` from the restored directory after fixing the underlying cause.
  2. Raise the inotify limit: sudo sysctl fs.inotify.max_user_watches=524288 (Linux).
  3. Raise the open-file limit: ulimit -n 4096 or the container equivalent.
  4. Verify the repo path still exists and is readable; re-clone or re-checkout if it was moved.

Example fix

// before
sysctl fs.inotify.max_user_watches  # 8192 -> EMFILE/ENOSPC
// after
sudo sysctl -w fs.inotify.max_user_watches=524288
gitnexus analyze --watch
Defensive patterns

Strategy: retry

Validate before calling

const fs = require('fs');
if (!fs.existsSync(repoPath)) throw new Error('repo path missing before watch');
if (process.platform === 'linux' && Number(readInotifyLimit()) < 8192) console.warn('raise fs.inotify.max_user_watches');

Try / catch

try {
  await runWatch();
} catch (e) {
  if (e instanceof WatchControlReloadError && /re-arm the filesystem watcher/.test(e.message)) {
    await sleep(1000);
    return runWatch(); // retry after transient EMFILE/ENOSPC
  }
  throw e;
}

Prevention

When it happens

Trigger: The watch directory or its parent was deleted/renamed mid-watch, the OS hit EMFILE/ENOSPC (too many open files / inotify watch limit), or permission on the watched directory changed.

Common situations: Long-running watch sessions in containers hitting the inotify limit (fs.inotify.max_user_watches), branch checkouts that rename the repo directory, or resource exhaustion on CI.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@0d1aed942f (2026-09-08). Data as JSON: /api/errors/4c1a1f236e139898. Report an issue: GitHub.