{"record":{"id":"fa43b6cef1bea881","repo":"gitbutlerapp/gitbutler","slug":"remote-with-url-url-already-exists-at-remote","errorCode":null,"errorMessage":"Remote with url '{url}' already exists at '{remote_name}'","messagePattern":"Remote with url '(.+?)' already exists at '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-repo/src/commands.rs","lineNumber":259,"sourceCode":"        if let Some(remote_name) = repo\n            .remote_names()\n            .iter()\n            .filter_map(|name| repo.find_remote(name).ok())\n            .find_map(|remote| {\n                remote\n                    .url(gix::remote::Direction::Fetch)\n                    .and_then(|remote_url| {\n                        if remote_url.to_bstring() == url {\n                            remote\n                                .name()\n                                .and_then(|n| n.as_symbol().map(ToOwned::to_owned))\n                        } else {\n                            None\n                        }\n                    })\n            })\n        {\n            bail!(\"Remote with url '{url}' already exists at '{remote_name}'\");\n        }\n\n        edit_repo_config(&repo, gix::config::Source::Local, |config| {\n            let mut section = config.section_mut_or_create_new(\"remote\", Some(name.into()))?;\n            section.push(\"url\", Some(url.as_bytes().as_bstr()))?;\n            ensure_config_value(\n                config,\n                &format!(\"remote.{name}.fetch\"),\n                &format!(\"+refs/heads/*:refs/remotes/{name}/*\"),\n            )?;\n            Ok(())\n        })?;\n        Ok(())\n    }\n\n    fn read_file_from_commit(\n        &self,\n        commit_id: gix::ObjectId,","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-repo/src/commands.rs#L241-L277","documentation":"Thrown by the add_remote command when a different remote already fetches from the exact same URL. After the name check passes, the command scans every configured remote's fetch URL and refuses a duplicate, naming the existing remote in the message. This dedupes remotes so GitButler never ends up with two names for the same server-side repository.","triggerScenarios":"Calling add_remote with a fresh name (e.g. 'upstream') whose URL string-equals the fetch URL of an existing remote (e.g. 'origin') - the filter_map over remote_names()/find_remote finds the match and the bail fires.","commonSituations":"Adding a second remote for the same GitHub repo (mirror/fork workflows) with the identical URL; copy-pasting the origin URL into the add-remote dialog; provisioning automation that runs on clones where the remote already exists under another name.","solutions":["Reuse the existing remote named in the error message instead of adding a new one","If the new remote must differ, use a genuinely different URL form (e.g. ssh vs https, or the fork's URL)","Remove the existing remote first if it is obsolete: git remote remove <existing_name>"],"exampleFix":"# before: add_remote('upstream', 'https://github.com/org/repo.git')\n#        -> \"Remote with url '...' already exists at 'origin'\"\n# after: origin already points there - just use it\ngit remote -v","handlingStrategy":"validation","validationCode":"let repo = gix::open(&workdir)?;\nlet url_taken = repo.remote_names().iter()\n    .filter_map(|n| repo.find_remote(n).ok())\n    .filter_map(|r| r.url(gix::remote::Direction::Fetch))\n    .any(|u| u.to_bstring() == url);\nif url_taken {\n    // a remote already fetches this URL; skip add_remote and reuse it\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Canonicalize URLs (ssh vs https) before comparing or adding","Design tooling around one remote per URL","Surface 'already exists at X' as an informational choice, not a failure"],"tags":["git","remote","duplicate","url"],"backgroundTag":"git-remote-url-already-exists","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}