{"record":{"id":"9b2b3d249eeda9ca","repo":"stablyai/orca","slug":"repo-has-multiple-remotes-remotes-join","errorCode":null,"errorMessage":"Repo has multiple remotes (${remotes.join(', ')}) and no default is configured. Set branch.<default>.remote.","messagePattern":"Repo has multiple remotes \\((.+?)\\) and no default is configured\\. Set branch\\.<default>\\.remote\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/git/repo.ts","lineNumber":851,"sourceCode":"    }\n  }\n\n  try {\n    const { stdout } = await gitExecFileAsync(['remote'], gitExecOptions(path, options))\n    const remotes = stdout\n      .split('\\n')\n      .map((line) => line.trim())\n      .filter(Boolean)\n    if (remotes.includes('origin')) {\n      return 'origin'\n    }\n    if (remotes.length === 1) {\n      return remotes[0]\n    }\n    if (remotes.length === 0) {\n      throw new Error('Repo has no configured git remotes.')\n    }\n    throw new Error(\n      `Repo has multiple remotes (${remotes.join(', ')}) and no default is configured. Set branch.<default>.remote.`\n    )\n  } catch (error) {\n    if (error instanceof Error) {\n      throw error\n    }\n    throw new Error('Failed to resolve default remote for repo.')\n  }\n}\n\nexport async function searchBaseRefs(path: string, query: string, limit = 25): Promise<string[]> {\n  return (await searchBaseRefDetails(path, query, limit)).map((entry) => entry.refName)\n}\n\nexport async function searchBaseRefDetails(\n  path: string,\n  query: string,\n  limit = 25","sourceCodeStart":833,"sourceCodeEnd":869,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/git/repo.ts#L833-L869","documentation":"getDefaultRemote throws when the repo has more than one remote, none of them is 'origin', no branch.<default>.remote config is set for the current default branch, and there is therefore no unambiguous choice. The message lists the remotes and tells the user to set branch.<default>.remote. Like 1052, it is rethrown verbatim by the surrounding catch.","triggerScenarios":"Calling getDefaultRemote on a repo with remotes like 'upstream' and 'fork' (no 'origin'), where the current default branch has no branch.<name>.remote config. The function refuses to guess which remote to push to.","commonSituations":"A fork-and-upstream workflow where 'origin' was renamed or never created; repos cloned then had 'origin' renamed to the fork name; multi-remote enterprise setups (e.g. 'github' + 'gitlab'); a branch checked out from one remote while the default branch tracks another and no branch.<default>.remote is set.","solutions":["Set the default remote for the branch: git config branch.<defaultBranch>.remote <remote> (and branch.<defaultBranch>.merge if you also want a merge ref).","Rename one of the remotes to 'origin' if that is the intended default: git remote rename <current> origin.","Remove remotes you no longer need so only one candidate remains.","Pass an explicit remote/pushTarget to the calling operation instead of relying on default resolution."],"exampleFix":"// before\n// repo has remotes: upstream, fork — no default\nconst remote = await getDefaultRemote(repoPath)\n\n// after: pin the default branch's remote\nawait run('git', ['config', `branch.${defaultBranch}.remote`, 'fork'], { cwd: repoPath })\nconst remote = await getDefaultRemote(repoPath)","handlingStrategy":"validation","validationCode":"async function repoHasUnambiguousDefault(path: string, defaultBranch: string | null): Promise<boolean> {\n  const { stdout } = await gitExecFileAsync(['remote'], { cwd: path })\n  const remotes = stdout.split('\\n').map((l) => l.trim()).filter(Boolean)\n  if (remotes.length === 1 || remotes.includes('origin')) return true\n  if (!defaultBranch) return false\n  try {\n    const { stdout: cfg } = await gitExecFileAsync(['config', '--get', `branch.${defaultBranch}.remote`], { cwd: path })\n    return Boolean(cfg.trim())\n  } catch { return false }\n}","typeGuard":"function isAmbiguousRemotes(error: unknown): boolean {\n  return error instanceof Error && /Repo has multiple remotes \\(.+\\) and no default is configured/.test(error.message)\n}","tryCatchPattern":"try { return await getDefaultRemote(repoPath) }\ncatch (error) {\n  if (isAmbiguousRemotes(error)) {\n    await gitExecFileAsync(['config', `branch.${defaultBranch}.remote`, 'fork'], { cwd: repoPath })\n    return await getDefaultRemote(repoPath)\n  }\n  throw error\n}","preventionTips":["Set branch.<default>.remote when a repo has multiple remotes and no 'origin'.","Rename the intended default remote to 'origin' as a simpler fix.","Pass an explicit remote/pushTarget to operations instead of relying on default resolution."],"tags":["git","remote","config","ambiguity"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}