{"record":{"id":"fd00a15c6065fb7a","repo":"yarnpkg/yarn","slug":"recursive-yarnrc-files-specifying-cwd-flags-ba","errorCode":null,"errorMessage":"Recursive .yarnrc files specifying --cwd flags. Bailing out.","messagePattern":"Recursive \\.yarnrc files specifying --cwd flags\\. Bailing out\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/rc.js","lineNumber":138,"sourceCode":"}\n\n// get a list of arguments from .yarnrc that apply to this commandName\nexport function getRcArgs(commandName: string, args: Array<string>, previousCwds?: Array<string> = []): Array<string> {\n  // for the cwd, use the --cwd arg if it was passed or else use process.cwd()\n  const origCwd = extractCwdArg(args) || process.cwd();\n\n  // get a map of command names and their arguments\n  const argMap = buildRcArgs(origCwd, args);\n\n  // concat wildcard arguments and arguments meant for this specific command\n  const newArgs = [...(argMap.get('*') || []), ...(argMap.get(commandName) || [])];\n\n  // check if the .yarnrc args specified a cwd\n  const newCwd = extractCwdArg(newArgs);\n  if (newCwd && newCwd !== origCwd) {\n    // ensure that we don't enter into a loop\n    if (previousCwds.indexOf(newCwd) !== -1) {\n      throw new Error(`Recursive .yarnrc files specifying --cwd flags. Bailing out.`);\n    }\n\n    //  if we have a new cwd then let's refetch the .yarnrc args relative to it\n    return getRcArgs(commandName, newArgs, previousCwds.concat(origCwd));\n  }\n\n  return newArgs;\n}\n","sourceCodeStart":120,"sourceCodeEnd":147,"githubUrl":"https://github.com/yarnpkg/yarn/blob/c2dda503f3759b5be5f0e24ecd9cf5c97a540147/src/rc.js#L120-L147","documentation":"When .yarnrc files chain --cwd flags into a cycle (A points to B, B points back to A), getRcArgs() detects the loop via previousCwds.indexOf(newCwd) !== -1 and bails. This prevents infinite recursion while following --cwd directives.","triggerScenarios":"Two or more .yarnrc files each specify --cwd to a directory whose .yarnrc points back to a previously-visited cwd. previousCwds tracks the visited chain.","commonSituations":"Accidentally creating circular .yarnrc --cwd references; misconfigured monorepo setups; symlinks creating directory loops.","solutions":["Inspect every .yarnrc in the chain and remove the circular --cwd entry","Consolidate .yarnrc configuration into a single file","Ensure no two .yarnrc files reference each other's directories via --cwd"],"exampleFix":"# before (.yarnrc in /proj/a)\n--cwd ../b\n# (.yarnrc in /proj/b)\n--cwd ../a\n# after — remove one reference\n# (.yarnrc in /proj/b) — delete the --cwd line","handlingStrategy":"validation","validationCode":"function detectCyclicCwd(yarnrcPaths, visited = new Set()) {\n  for (const p of yarnrcPaths) {\n    const cwd = extractCwdArg(parseYarnrc(p));\n    if (cwd && visited.has(cwd)) return { cyclic: true, cwd };\n    if (cwd) visited.add(cwd);\n  }\n  return { cyclic: false, cwd: null };\n}","typeGuard":"function isCyclicCwdChain(previousCwds: string[], newCwd: string): boolean {\n  return previousCwds.indexOf(newCwd) !== -1;\n}","tryCatchPattern":"try {\n  const args = getRcArgs(commandName, args);\n} catch (e) {\n  if (e.message.includes('Recursive .yarnrc')) {\n    // fall back to a single explicit .yarnrc or skip --cwd\n  }\n}","preventionTips":["Avoid --cwd in .yarnrc files; pass --cwd on the CLI instead","Audit monorepo .yarnrc files for mutual references","Use symlinks cautiously near .yarnrc locations"],"tags":["yarnrc","configuration","recursion"],"backgroundTag":null,"analyzedSha":"c2dda503f3759b5be5f0e24ecd9cf5c97a540147","analyzedAt":"2026-08-13T04:17:06.305Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}