{"record":{"id":"35d8499891aaeabc","repo":"abhigyanpatwari/GitNexus","slug":"trusted-cache-directory-env-must-be-outside-the","errorCode":null,"errorMessage":"${TRUSTED_CACHE_DIRECTORY_ENV} must be outside the analyzer package and build roots","messagePattern":"(.+?) must be outside the analyzer package and build roots","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/analyzer-identity.ts","lineNumber":2112,"sourceCode":"): string | null {\n  // An explicit location is a trusted operator/test override and therefore\n  // remains authoritative, including when the secure default is unavailable.\n  if (options.cacheDirectory) {\n    const explicit = path.resolve(options.cacheDirectory);\n    try {\n      // Create it before any build/dependency directory guards are captured.\n      // A cache nested immediately under a package root then changes that\n      // parent's directory state once, not after we persist the first entry.\n      mkdirSync(explicit, { recursive: true, mode: 0o700 });\n    } catch {\n      /* persistence remains optional and will fail closed */\n    }\n    return explicit;\n  }\n  const configured = trustedEnvironmentCacheDirectory();\n  if (configured) {\n    if (isInside(packageRoot, configured) || isInside(buildRoot, configured)) {\n      throw new Error(\n        `${TRUSTED_CACHE_DIRECTORY_ENV} must be outside the analyzer package and build roots`,\n      );\n    }\n    return configured;\n  }\n  return defaultCacheDirectory();\n}\n\nfunction hasTrustedCacheOverride(options: AnalyzerIdentityResolveOptions): boolean {\n  return (\n    options.cacheDirectory !== undefined || process.env[TRUSTED_CACHE_DIRECTORY_ENV] !== undefined\n  );\n}\n\nfunction identityCacheKey(\n  packageRoot: string,\n  buildRoot: string,\n  runtimeVariant: RuntimeVariant,","sourceCodeStart":2094,"sourceCodeEnd":2130,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/core/analyzer-identity.ts#L2094-L2130","documentation":"Thrown by cacheDirectory when the env-var-configured cache directory lies inside the analyzer packageRoot or buildRoot. The cache must be external to both, because writing identity-cache files inside the scanned roots would itself mutate the directory-state guards that the identity receipt depends on — creating a feedback loop that invalidates the cache on every write.","triggerScenarios":"trustedEnvironmentCacheDirectory returned a valid external-looking path, but isInside(packageRoot, configured) or isInside(buildRoot, configured) is true. E.g. setting the cache to `<packageRoot>/.cache/gn-id` or `<buildRoot>/../something` that resolves back inside the build tree.","commonSituations":"Operator tried to keep the cache co-located with the project for convenience (`./.gitnexus-id-cache`); a CI that sets the cache to a subdirectory of the checkout; a monorepo where the cache path was computed relative to the package and landed inside it; a buildRoot that overlaps packageRoot (e.g. `dist/` inside the package).","solutions":["Move the cache outside both roots: `/var/cache/gitnexus-analyzer-identity` or `$HOME/.cache/gitnexus-analyzer-identity`.","Verify: `case \"$CACHE\" in \"$PKG_ROOT\"/*|\"$BUILD_ROOT\"/*) echo overlaps;; esac`.","If you must keep it near the project, put it in a sibling directory (e.g. `../gn-id-cache` resolved to absolute).","If no external writable location exists, unset the env var so the secure default temp location is used (which is already chosen to be external)."],"exampleFix":"# before: cache nested inside the package root\n#   export GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/repo/.cache/gn-id\n#   -> \"...must be outside the analyzer package and build roots\"\n#\n# after: external writable location\n#   export GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/var/cache/gitnexus-analyzer-identity\n#   mkdir -p /var/cache/gitnexus-analyzer-identity && chmod 700 /var/cache/gitnexus-analyzer-identity","handlingStrategy":"validation","validationCode":"const path = require('node:path');\nfunction isInside(parent, candidate) {\n  const rel = path.relative(parent, candidate);\n  return rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);\n}\nfunction validateCacheOutsideRoots(packageRoot, buildRoot) {\n  const v = process.env.GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR;\n  if (!v) return;\n  if (isInside(packageRoot, v) || isInside(buildRoot, v)) {\n    throw new Error(`Cache ${v} is inside package/build root; move it outside.`);\n  }\n}\n// validateCacheOutsideRoots(process.cwd(), path.join(process.cwd(),'dist'));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Place the cache in a sibling or system directory, never inside the checkout or build output.","Use /var/cache, $HOME/.cache, or a dedicated volume.","If no external location is writable, unset the env var to use the secure default temp location.","Remember: writing inside the scanned roots would invalidate the identity on every cache write."],"tags":["analyzer-identity","cache","configuration","environment","feedback-loop"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}