abhigyanpatwari/GitNexus · error

Analyzer runtime payload directory is unavailable: ${absolut

Error message

Analyzer runtime payload directory is unavailable: ${absoluteDir}

What it means

Thrown by collectArtifacts when recordDirectoryGuard returns false for a directory it is about to scan. recordDirectoryGuard fails (returns false) only when snapshotDirectoryInventory throws — meaning the directory cannot be inventoried via readdir+stat. The throw aborts the runtime-payload scan because the identity receipt cannot cover a directory it cannot observe.

Source

Thrown at gitnexus/src/core/analyzer-identity.ts:1320

  return lower !== 'package.json';
}

function collectArtifacts(
  root: string,
  canonicalPrefix: string,
  directoryGuards: Map<string, DependencyDirectoryGuard>,
  options: AnalyzerIdentityResolveOptions,
  budget: RuntimeArtifactScanBudget,
  limits: AnalyzerIdentityTraversalLimits,
): RuntimeArtifact[] {
  const artifacts: RuntimeArtifact[] = [];
  const pending: Array<{ absoluteDir: string; depth: number }> = [{ absoluteDir: root, depth: 0 }];
  while (pending.length > 0) {
    const next = pending.pop();
    if (!next) break;
    const { absoluteDir, depth } = next;
    if (!recordDirectoryGuard(directoryGuards, absoluteDir)) {
      throw new Error(`Analyzer runtime payload directory is unavailable: ${absoluteDir}`);
    }
    const entries = readDirectory(absoluteDir, options);
    budget.entries += entries.length;
    if (budget.entries > limits.runtimeEntries) {
      throw new Error(
        `Analyzer runtime payload scan exceeded ${limits.runtimeEntries} entries: ${root}`,
      );
    }
    for (const entry of entries) {
      const absolutePath = path.join(absoluteDir, entry.name);
      const relativePath = path.relative(root, absolutePath).split(path.sep).join('/');
      const stat = lstatSync(absolutePath);
      // Nested dependencies are collected from their manifests as separate
      // packages. Only prune those separately traversed trees and VCS
      // metadata; generic cache/model directories can contain loadable code,
      // native addons, Wasm modules, or data consumed by the runtime.
      //
      // Pruning is decided by NAME alone. These four names never carry analyzer

View on GitHub (pinned to d540b00184)

Solutions

  1. Re-run the analyze once the filesystem is quiescent — close concurrent builds/installs/IDE indexers and retry.
  2. Check the named absoluteDir: `ls -la <absoluteDir>` and `readlink -f <absoluteDir>` to confirm it exists and is readable.
  3. If a dangling symlink is the cause, repair or remove it (`npm install` to rebuild node_modules, or `rm` the broken link).
  4. Run the analyzer from a clean checkout or freshly installed tree so no partial deletion races the scan.

Example fix

// before: analyzer runs while `tsc --watch` deletes and recreates dist/
//   -> "Analyzer runtime payload directory is unavailable: /pkg/dist"
//
// after: stop concurrent writers, then resolve identity
//   $ pkill -f tsc  (or close the watch)
//   $ node .gitnexus/run.cjs analyze --index-only
Defensive patterns

Strategy: try-catch

Validate before calling

const fs = require('node:fs');
const path = require('node:path');
function isDirectoryReadable(dir) {
  let st;
  try { st = fs.lstatSync(dir); } catch { return false; }
  if (!st.isDirectory()) return false;
  try { fs.readdirSync(dir); return true; } catch { return false; }
}
// Pre-walk the package tree to confirm every dir is readable before resolveAnalyzerRunnerIdentity.
// Only a shallow check; the real scan is deeper, but this catches the common permission/deletion case.

Try / catch

try {
  identity = resolveAnalyzerRunnerIdentity(analyzerModuleUrl, options);
} catch (err) {
  if (err.message.startsWith('Analyzer runtime payload directory is unavailable:')) {
    const dir = err.message.split(': ').slice(1).join(': ');
    log.warn(`Directory ${dir} vanished during identity resolution; ensure no concurrent build is mutating the tree.`);
    // do not retry in a tight loop; surface to the user / scheduler with backoff
  }
  throw err;
}

Prevention

When it happens

Trigger: collectArtifacts pops a pending directory and calls recordDirectoryGuard(directoryGuards, absoluteDir); if the directory was deleted, lost permissions, or turned into a broken symlink/non-directory between enqueue and scan, snapshotDirectoryInventory throws and recordDirectoryGuard returns false, triggering this error.

Common situations: A concurrent process (build, IDE, package manager) deleting or moving directories under the package while the analyzer resolves its identity; a node_modules entry that is a dangling symlink to a removed target; permission errors after a `chown`/container rebuild where the analyzer process cannot read a subdirectory; an OS-level antivirus quarantining a directory mid-scan.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/e2b28a86d66a4466. Report an issue: GitHub.