{"record":{"id":"dbe91a6b37378d11","repo":"abhigyanpatwari/GitNexus","slug":"gitnexus-rc-filename-prev-and-key-bo","errorCode":null,"errorMessage":"${GITNEXUS_RC_FILENAME}: \"${prev}\" and \"${key}\" both configure the same option; set only one.","messagePattern":"(.+?): \"(.+?)\" and \"(.+?)\" both configure the same option; set only one\\.","errorType":"validation","errorClass":"GitNexusRcError","httpStatus":null,"severity":"error","filePath":"gitnexus/src/cli/analyze-config.ts","lineNumber":344,"sourceCode":"): Partial<AnalyzeOptions> => {\n  const out: Partial<AnalyzeOptions> = {};\n  const setBy = new Map<keyof AnalyzeOptions, string>();\n\n  for (const [key, value] of Object.entries(obj)) {\n    if (allowNestedKey && key === NESTED_KEY) continue; // handled separately\n    // `Object.hasOwn`, not a truthiness check: a plain-object lookup like\n    // `KEY_SPECS[\"__proto__\"]` returns an inherited member (Object.prototype,\n    // truthy) and would slip past `if (!spec)`, hitting the wrong error branch\n    // instead of the documented \"Unknown key\" message (#1996 tri-review P3).\n    if (!Object.hasOwn(KEY_SPECS, key)) {\n      throw new GitNexusRcError(\n        `Unknown key \"${key}\" in ${GITNEXUS_RC_FILENAME}. ${ALLOWED_KEYS_HINT}`,\n      );\n    }\n    const spec = KEY_SPECS[key];\n    const prev = setBy.get(spec.target);\n    if (prev && prev !== key) {\n      throw new GitNexusRcError(\n        `${GITNEXUS_RC_FILENAME}: \"${prev}\" and \"${key}\" both configure the same option; set only one.`,\n      );\n    }\n    setBy.set(spec.target, key);\n    (out as Record<string, unknown>)[spec.target] = normalizeValue(spec.kind, value, key);\n  }\n\n  return out;\n};\n\n/**\n * Locate, read, parse, validate, and normalize `.gitnexusrc` at `repoRoot`.\n *\n * @returns the normalized config defaults, or `undefined` when no file exists\n *          (the normal case). Throws {@link GitNexusRcError} on any problem.\n */\nexport function loadAnalyzeConfig(repoRoot: string): Partial<AnalyzeOptions> | undefined {\n  const filePath = path.join(repoRoot, GITNEXUS_RC_FILENAME);","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/ac9a4e9abd8fd3058c070b72c23402a4f887929a/gitnexus/src/cli/analyze-config.ts#L326-L362","documentation":"Several .gitnexusrc keys are aliases for the same underlying AnalyzeOptions target (branch→defaultBranch, skipContextFiles/skipAiContext→skipAgentsMd, noStats→stats). normalizeLevel tracks which physical key set each target; if two different aliases both appear at the same level, the config is ambiguous and rejected.","triggerScenarios":"{\"defaultBranch\": \"main\", \"branch\": \"develop\"}; {\"skipAgentsMd\": true, \"skipContextFiles\": true}; {\"stats\": true, \"noStats\": true} — each pair collides on one target option; applies inside the nested \"analyze\" block too (flat vs nested across levels is allowed, nested wins).","commonSituations":"Merging rc files from two teams that each standardized on a different alias; incremental edits adding the newer alias without removing the old one; docs examples that mix aliases in one snippet.","solutions":["Delete one of the two aliases named in the message — the error quotes both keys explicitly","Standardize the team's .gitnexusrc on one alias set and enforce it in review","If you need per-command override, put the base value flat and the override in the nested \"analyze\" object (nested legitimately overrides flat)"],"exampleFix":"// before (.gitnexusrc)\n{\"defaultBranch\": \"main\", \"branch\": \"develop\"}\n// after\n{\"defaultBranch\": \"develop\"}","handlingStrategy":"validation","validationCode":"const ALIAS_GROUPS: string[][] = [\n  ['defaultBranch', 'branch'],\n  ['skipAgentsMd', 'skipContextFiles', 'skipAiContext'],\n  ['stats', 'noStats'],\n];\nconst keys = new Set(Object.keys(rc));\nfor (const group of ALIAS_GROUPS) {\n  const present = group.filter((k) => keys.has(k));\n  if (present.length > 1) throw new Error(`Pick one of: ${present.join(', ')}`);\n}","typeGuard":null,"tryCatchPattern":"catch (err) {\n  if (err instanceof GitNexusRcError && err.message.includes('both configure the same option')) {\n    // message names both keys; delete one of them\n  }\n}","preventionTips":["Standardize the team on one alias per option and lint the others out","Use the nested \"analyze\" object for overrides instead of mixing aliases flat"],"tags":["config","validation","aliases","gitnexusrc"],"backgroundTag":"conflicting-config-keys","analyzedSha":"ac9a4e9abd8fd3058c070b72c23402a4f887929a","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}