{"record":{"id":"d2ca35a58d3449a7","repo":"abhigyanpatwari/GitNexus","slug":"keeping-registry-entry-despite-fs-access-failure","errorCode":null,"errorMessage":"Keeping registry entry despite fs.access failure (not provably absent); not pruning to avoid mass registry wipe.","messagePattern":"Keeping registry entry despite fs\\.access failure \\(not provably absent\\); not pruning to avoid mass registry wipe\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"gitnexus/src/storage/repo-manager.ts","lineNumber":1541,"sourceCode":"    if (!indexFound) {\n      try {\n        await fs.access(path.join(entry.storagePath, LEGACY_METADATA_FILE));\n        indexFound = true;\n      } catch (err: any) {\n        if (isMissingFilesystemError(err)) lastMissingError = err;\n        else if (!firstNonMissingError) firstNonMissingError = err;\n      }\n    }\n\n    if (indexFound) {\n      valid.push(entry);\n    } else if (!firstNonMissingError && lastMissingError) {\n      // Index genuinely removed — safe to prune\n    } else {\n      // Not provably absent — keep entry to prevent mass registry wipe.\n      // Warn so an I/O storm becomes observable instead of silently\n      // keeping (or, pre-fix, silently wiping) entries.\n      logger.warn(\n        { name: entry.name, storagePath: entry.storagePath, code: firstNonMissingError?.code },\n        'Keeping registry entry despite fs.access failure (not provably absent); not pruning to avoid mass registry wipe.',\n      );\n      valid.push(entry);\n    }\n  }\n\n  // If we pruned any entries, save the cleaned registry — under the lock, and\n  // only then. The validation walk above is read-only (an fs.access per entry,\n  // slow on a network mount or a large registry) and the common case prunes\n  // nothing, so holding the global lock across it would serialize every\n  // `gitnexus augment` behind unrelated registry work for no benefit. Re-read\n  // inside the lock and drop the provably-absent paths from that fresh\n  // snapshot, so a concurrent registration in the validation window survives.\n  if (valid.length !== entries.length) {\n    const pruned = new Set(\n      entries.filter((entry) => !valid.includes(entry)).map((entry) => entry.path),\n    );","sourceCodeStart":1523,"sourceCodeEnd":1559,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/storage/repo-manager.ts#L1523-L1559","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the code field: EACCES points at permissions, EIO/network codes at mount health","Restore access or remount, then re-run the validation — provably absent entries will then prune cleanly","Never hand-mass-edit the registry file to force pruning; let a healthy re-run do it under the lock"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"try {\n  await fs.access(entry.storagePath);\n  // exists — entry is valid, keep it\n} catch (e) {\n  if ((e as NodeJS.ErrnoException)?.code !== 'ENOENT') {\n    // not provably absent — the entry will be kept to avoid a mass wipe;\n    // fix the I/O condition (permissions/mount) and re-run validation.\n  }\n}","typeGuard":"function isMissingError(e: unknown): e is NodeJS.ErrnoException {\n  return (e as NodeJS.ErrnoException)?.code === 'ENOENT';\n}","tryCatchPattern":null,"preventionTips":["Keep registry storage on reliable local disk","Re-run validation after mount or permission recovery instead of hand-editing the registry","Keep-on-doubt protects against mass registry wipes — do not work around it with manual edits"],"tags":["registry","filesystem","io","data-safety","conservative-failure"],"backgroundTag":"transient-io-error","analyzedSha":"0d1aed942f0e8b5d3bac27519fff441aceea722d","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}