{"record":{"id":"e2b28a86d66a4466","repo":"abhigyanpatwari/GitNexus","slug":"analyzer-runtime-payload-directory-is-unavailable","errorCode":null,"errorMessage":"Analyzer runtime payload directory is unavailable: ${absoluteDir}","messagePattern":"Analyzer runtime payload directory is unavailable: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/analyzer-identity.ts","lineNumber":1322,"sourceCode":"  return lower !== 'package.json';\n}\n\nfunction collectArtifacts(\n  root: string,\n  canonicalPrefix: string,\n  directoryGuards: Map<string, DependencyDirectoryGuard>,\n  options: AnalyzerIdentityResolveOptions,\n  budget: RuntimeArtifactScanBudget,\n  limits: AnalyzerIdentityTraversalLimits,\n): RuntimeArtifact[] {\n  const artifacts: RuntimeArtifact[] = [];\n  const pending: Array<{ absoluteDir: string; depth: number }> = [{ absoluteDir: root, depth: 0 }];\n  while (pending.length > 0) {\n    const next = pending.pop();\n    if (!next) break;\n    const { absoluteDir, depth } = next;\n    if (!recordDirectoryGuard(directoryGuards, absoluteDir)) {\n      throw new Error(`Analyzer runtime payload directory is unavailable: ${absoluteDir}`);\n    }\n    const entries = readDirectory(absoluteDir, options);\n    budget.entries += entries.length;\n    if (budget.entries > limits.runtimeEntries) {\n      throw new Error(\n        `Analyzer runtime payload scan exceeded ${limits.runtimeEntries} entries: ${root}`,\n      );\n    }\n    for (const entry of entries) {\n      const absolutePath = path.join(absoluteDir, entry.name);\n      const relativePath = path.relative(root, absolutePath).split(path.sep).join('/');\n      const stat = lstatSync(absolutePath);\n      // Nested dependencies are collected from their manifests as separate\n      // packages. Only prune those separately traversed trees and VCS\n      // metadata; generic cache/model directories can contain loadable code,\n      // native addons, Wasm modules, or data consumed by the runtime.\n      //\n      // Pruning is decided by NAME alone. These four names never carry analyzer","sourceCodeStart":1304,"sourceCodeEnd":1340,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/52924ef12c2290ceee4612526a828ec4cdf2047f/gitnexus/src/core/analyzer-identity.ts#L1304-L1340","documentation":"Before scanning a runtime payload directory, the code records a directory-inventory guard (double-read stat + entries digest); if that snapshot fails — directory deleted, replaced by a file, made unreadable, or unstable across the guard's two reads — recordDirectoryGuard returns false and this error throws with the directory path. Guards exist because the identity receipt must remain verifiable after the fact: a directory whose inventory could not even be captured cannot be covered.","triggerScenarios":"A dependency package directory disappearing or being swapped mid-scan — concurrent 'npm uninstall'/'npm update' removing the package, a package manager garbage-collecting a store, or permissions changing under the process — while collectArtifacts walks runtime package trees during analyze/status.","commonSituations":"Analyzer runs racing an install/upgrade in another terminal; CI cache eviction pruning node_modules during the job; Docker layers or FUSE mounts lazily evicting directories; two gitnexus processes scanning while one cleans.","solutions":["Re-run once installs/upgrades/cleanups of the gitnexus tree have finished — the condition is transient.","Serialize package-manager operations and analyze runs in CI scripts.","Ensure the process has stable read access (permissions, mounted volumes) to the analyzer's node_modules for the whole run."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"function isPayloadDirectoryUnavailableError(error: unknown): boolean {\n  return error instanceof Error && /^Analyzer runtime payload directory is unavailable:/.test(error.message);\n}","tryCatchPattern":"try {\n  identity = resolveAnalyzerRunnerIdentity(import.meta.url);\n} catch (error) {\n  if (!isPayloadDirectoryUnavailableError(error)) throw error;\n  await sleep(500); // wait out the concurrent uninstall/cache eviction\n  identity = resolveAnalyzerRunnerIdentity(import.meta.url);\n}","preventionTips":["Do not uninstall/upgrade the analyzer's node_modules while analyze or status is running.","Disable CI cache eviction/prune steps that touch node_modules during the analysis job.","Ensure stable read permissions on the analyzer install for the whole run."],"tags":["gitnexus","analyzer-identity","filesystem","toctou","node-modules"],"backgroundTag":"directory-changed-during-scan","analyzedSha":"52924ef12c2290ceee4612526a828ec4cdf2047f","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}