{"record":{"id":"aaf1280e17053711","repo":"abhigyanpatwari/GitNexus","slug":"local-path-is-required","errorCode":null,"errorMessage":"local_path is required","messagePattern":"local_path is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/auto-sync/path-security.ts","lineNumber":107,"sourceCode":"    root,\n    realRoot,\n    'Configured clone root realpath escaped its normalized path',\n  );\n  assertNotDangerousRoot(realRoot);\n  assertNotGitNexusInternalRoot(realRoot);\n  const quarantineRoot = path.join(getAutoSyncWatchDir(), 'quarantine');\n  await pruneQuarantineEntries(quarantineRoot);\n\n  return {\n    root: realRoot,\n    quarantineRoot,\n    quarantineRetentionDays: QUARANTINE_RETENTION_DAYS,\n  };\n}\n\nexport function normalizeConfiguredCloneRoot(localPath: string): string {\n  const value = localPath.trim();\n  if (!value) throw new Error('local_path is required');\n  if (!path.isAbsolute(value)) throw new Error('local_path must be an absolute path');\n  if (value.split(path.sep).includes('..')) {\n    throw new Error('local_path must be normalized and must not contain traversal segments');\n  }\n  const resolved = path.resolve(value);\n  if (resolved !== path.normalize(value)) {\n    throw new Error('local_path must be normalized and must not contain traversal segments');\n  }\n  return resolved;\n}\n\nexport async function quarantineAutoSyncPartial(\n  targetDir: string,\n  quarantineRoot: string,\n): Promise<string> {\n  await fs.mkdir(quarantineRoot, { recursive: true, mode: 0o700 });\n  const base = path.basename(targetDir);\n  const stamp = new Date().toISOString().replace(/[:.]/g, '-');","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/core/auto-sync/path-security.ts#L89-L125","documentation":"normalizeConfiguredCloneRoot validates the local_path of an auto-sync clone root. An empty value (after trimming whitespace) has no meaning, so it throws 'local_path is required' immediately at config parse time. The check guarantees downstream path-resolution code always operates on a real path string.","triggerScenarios":"parseAutoSyncConfig is called with local_path set to \"\", \"   \", or null/undefined coerced to an empty string.","commonSituations":"Missing local_path key in the auto-sync config file, an env var placeholder that expanded to empty (e.g. ${CLONE_ROOT} unset), or YAML with `local_path:` left blank.","solutions":["Set local_path in the config to the absolute path of the existing clone root directory.","If it comes from an environment variable, export that variable before running.","Re-run parseAutoSyncConfig to confirm the config loads."],"exampleFix":"// before (config)\nlocal_path: \"\"\n// after (config)\nlocal_path: \"/home/dev/work/gitnexus-clones\"","handlingStrategy":"validation","validationCode":"const localPath = process.env.CLONE_ROOT ?? '';\nif (!localPath.trim()) throw new Error('local_path must be set to a non-empty absolute path before loading auto-sync config');","typeGuard":"function hasLocalPath(cfg: unknown): cfg is { local_path: string } {\n  return typeof cfg === 'object' && cfg !== null && 'local_path' in cfg && typeof (cfg as any).local_path === 'string' && (cfg as any).local_path.trim() !== '';\n}","tryCatchPattern":"try {\n  parseAutoSyncConfig(raw);\n} catch (err) {\n  if (err.message === 'local_path is required') {\n    console.error('Set local_path in the auto-sync config to an existing absolute directory.');\n    process.exitCode = 1;\n  } else throw err;\n}","preventionTips":["Always set local_path explicitly; never leave the key blank in YAML.","Fail fast on unset environment variables with ${VAR:?err} in shell wrappers.","Require the key in config schema validation before parsing."],"tags":["config","path","validation","auto-sync"],"backgroundTag":"missing-required-config-field","analyzedSha":"0d1aed942f0e8b5d3bac27519fff441aceea722d","analyzedAt":"2026-09-08T00:40:44.970Z","contentChangedAt":"2026-09-08T00:40:44.970Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}