abhigyanpatwari/GitNexus · warning · GitNexusRcError

: branch name must not contain whitespace.

Error message

${source}: branch name must not contain whitespace.

What it means

On Windows, libuv resolves db.close() before the kernel releases the file handle; a subsequent new Database(samePath) can race the release. The post-close probe (HANDLE_RELEASE_PROBE_ATTEMPTS=5 × HANDLE_RELEASE_PROBE_DELAY_MS=50 ≈ 250ms budget) forces residual locks to surface so open-time retry absorbs the lag. This warn means the probe budget was exhausted with a lock code still in flight — most often antivirus (Windows Defender) holding the file past 250ms.

Solutions

  1. Add an antivirus/Defender exclusion for the GitNexus storage directory — the message's own recommendation
  2. Retry the operation: the next openLbugConnection still absorbs residual lag via its open-time retry, so a transient occurrence is safe
  3. Pause sync/indexing tools (OneDrive, search indexer) over the storage directory
  4. If it repeats on every close/reopen despite exclusions, increase the gap between close and reopen in the calling code
Defensive patterns

Strategy: retry

Validate before calling

import { open } from 'node:fs/promises';
// Windows: probe handle availability before re-opening the same DB path
if (process.platform === 'win32') {
  let h: Awaited<ReturnType<typeof open>> | undefined;
  try { h = await open(dbPath, 'r+'); } finally { await h?.close(); }
}

Type guard

const isWindowsLockErrno = (e: unknown): boolean => {
  const code = (e as NodeJS.ErrnoException | null)?.code;
  return code === 'EBUSY' || code === 'EPERM' || code === 'EACCES';
};

Try / catch

try {
  await openLbugConnection(dbPath);
} catch (e) {
  if (isWindowsLockErrno(e)) {
    // residual close lag or AV hold — back off and retry once before failing
    await new Promise((r) => setTimeout(r, 250));
    return openLbugConnection(dbPath);
  }
  throw e;
}

Prevention

When it happens

Trigger: process.platform === 'win32' and waitForWindowsHandleRelease(closingDbPath) returns false after the retry budget — close immediately followed by reopen of the same DB path in one process, with Defender/AV scanning the storage directory and extending handle release beyond the probe window.

Common situations: Real-time AV scanning of the GitNexus storage directory; tight close-then-reopen cycles during tests or repeated analyze runs; file-system filter drivers (indexers, sync clients like OneDrive/Dropbox) holding the handle.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@52924ef12c (2026-08-20). Data as JSON: /api/errors/3408d725bd0c0fff. Report an issue: GitHub.

Appendix: source

Thrown at gitnexus/src/cli/analyze-config.ts:173

  }
};

/**
 * Validate a user-supplied branch name (from CLI or `.gitnexusrc`). Returns the
 * trimmed name or throws {@link GitNexusRcError}. Conservative but accepts the
 * shapes real branches use (`feature/foo-bar`, `release/1.2`, `develop`).
 */
export function validateBranchName(value: string, source: string): string {
  const trimmed = value.trim();
  if (!trimmed) {
    throw new GitNexusRcError(`${source}: branch name must not be empty.`);
  }
  if (trimmed.length > BRANCH_MAX_LENGTH) {
    throw new GitNexusRcError(`${source}: branch name is too long (max ${BRANCH_MAX_LENGTH}).`);
  }
  assertNoHiddenChars(trimmed, source);
  if (/\s/.test(trimmed)) {
    throw new GitNexusRcError(`${source}: branch name must not contain whitespace.`);
  }
  // git ref-name rules (subset): reject characters git itself forbids in refs.
  if (/[~^:?*[\\]/.test(trimmed)) {
    throw new GitNexusRcError(
      `${source}: branch name contains characters not allowed in a git ref (~ ^ : ? * [ \\).`,
    );
  }
  if (trimmed.startsWith('-')) {
    throw new GitNexusRcError(`${source}: branch name must not start with "-".`);
  }
  if (trimmed.includes('..')) {
    throw new GitNexusRcError(`${source}: branch name must not contain "..".`);
  }
  // Git permits a backtick in a ref, but the branch is embedded inside a
  // Markdown inline-code span in the generated AGENTS.md/CLAUDE.md regression
  // example, where a backtick would close the span early and let the rest of
  // the template render as instruction text. Reject it at this single
  // chokepoint so all three tiers (CLI flag, .gitnexusrc, auto-detect via

View on GitHub (pinned to 52924ef12c)