abhigyanpatwari/GitNexus · warning

Keeping registry entry despite fs.access failure (not provab

Error message

Keeping registry entry despite fs.access failure (not provably absent); not pruning to avoid mass registry wipe.

What it means

During registry validation, each entry's storage path is probed with fs.access. An entry is pruned only when absence is proven (clean ENOENT, no other error); if any probe failed with a non-missing error (EACCES, EIO, network hiccup), the entry is kept — deliberately, so an I/O storm cannot cause a mass registry wipe. This warning makes that kept-despite-doubt outcome observable instead of silent (the pre-fix behavior silently wiped).

Source

Thrown at gitnexus/src/storage/repo-manager.ts:1541

    if (!indexFound) {
      try {
        await fs.access(path.join(entry.storagePath, LEGACY_METADATA_FILE));
        indexFound = true;
      } catch (err: any) {
        if (isMissingFilesystemError(err)) lastMissingError = err;
        else if (!firstNonMissingError) firstNonMissingError = err;
      }
    }

    if (indexFound) {
      valid.push(entry);
    } else if (!firstNonMissingError && lastMissingError) {
      // Index genuinely removed — safe to prune
    } else {
      // Not provably absent — keep entry to prevent mass registry wipe.
      // Warn so an I/O storm becomes observable instead of silently
      // keeping (or, pre-fix, silently wiping) entries.
      logger.warn(
        { name: entry.name, storagePath: entry.storagePath, code: firstNonMissingError?.code },
        'Keeping registry entry despite fs.access failure (not provably absent); not pruning to avoid mass registry wipe.',
      );
      valid.push(entry);
    }
  }

  // If we pruned any entries, save the cleaned registry — under the lock, and
  // only then. The validation walk above is read-only (an fs.access per entry,
  // slow on a network mount or a large registry) and the common case prunes
  // nothing, so holding the global lock across it would serialize every
  // `gitnexus augment` behind unrelated registry work for no benefit. Re-read
  // inside the lock and drop the provably-absent paths from that fresh
  // snapshot, so a concurrent registration in the validation window survives.
  if (valid.length !== entries.length) {
    const pruned = new Set(
      entries.filter((entry) => !valid.includes(entry)).map((entry) => entry.path),
    );

View on GitHub (pinned to 0d1aed942f)

Solutions

  1. Check the code field: EACCES points at permissions, EIO/network codes at mount health
  2. Restore access or remount, then re-run the validation — provably absent entries will then prune cleanly
  3. Never hand-mass-edit the registry file to force pruning; let a healthy re-run do it under the lock
Defensive patterns

Strategy: validation

Validate before calling

try {
  await fs.access(entry.storagePath);
  // exists — entry is valid, keep it
} catch (e) {
  if ((e as NodeJS.ErrnoException)?.code !== 'ENOENT') {
    // not provably absent — the entry will be kept to avoid a mass wipe;
    // fix the I/O condition (permissions/mount) and re-run validation.
  }
}

Type guard

function isMissingError(e: unknown): e is NodeJS.ErrnoException {
  return (e as NodeJS.ErrnoException)?.code === 'ENOENT';
}

Prevention

When it happens

Trigger: Running an operation that walks/validates the registry while storage-path accesses fail with non-ENOENT errors: permission denied on parts of the storage tree, a flaky NFS/SMB mount, transient I/O errors. Those entries survive validation conservatively.

Common situations: Storage on a network mount that blipped mid-walk; a chmod/chown of the storage dir; sandboxed environments denying access; truly stale entries then not pruned until a healthy re-run.

Related errors


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