gitbutlerapp/gitbutler · error

Remote with url already exists.

Error message

Remote ${sameUrlRemote.name} with url ${sameUrlRemote.url} already exists.

What it means

Thrown by remotesService.addRemote when a remote with the same URL already exists, even under a different name. The comment in the code notes this should not happen normally and indicates the UI incorrectly showed an 'apply from fork' button for a project that already has this remote. It's a guard against duplicate remotes pointing at the same URL.

Solutions

  1. Refresh the remote list before offering the 'apply from fork' action so already-added URLs don't produce the button.
  2. If the URL already exists, reuse the existing remote instead of adding a new one.
  3. Catch the error in the UI and inform the user the fork remote is already configured.
Defensive patterns

Strategy: validation

Validate before calling

const remotes = await remotesService.remotes(projectId);
if (remotes.some(r => r.url === url)) return; // already added; reuse it

Try / catch

try {
  await remotesService.addRemote(projectId, name, url);
} catch (e) {
  if (String(e).includes('with url')) showToast('This fork is already added');
}

Prevention

When it happens

Trigger: Calling addRemote(projectId, name, url) where some existing remote already has the exact same url, typically via an 'apply from fork' UI action.

Common situations: UI state out of sync with the actual git remote list — fork already applied under another name; adding the same fork to two stacks; stale remote list cache.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/0c500e38fbbfbd84. Report an issue: GitHub.

Appendix: source

Thrown at apps/desktop/src/lib/git/remotesService.ts:29

export class RemotesService {
	constructor(private backend: IBackend) {}
	async remotes(projectId: string) {
		return await this.backend.invoke<GitRemote[]>("list_remotes", { projectId });
	}

	async addRemote(projectId: string, name: string, url: string) {
		const remotes = await this.remotes(projectId);

		const sameNameRemote = remotes.find((remote) => remote.name === name);
		if (sameNameRemote) {
			throw new Error(`Remote with name ${sameNameRemote.name} already exists.`);
		}

		const sameUrlRemote = remotes.find((remote) => remote.url === url);
		if (sameUrlRemote) {
			// This should not happen, and indicates we are incorrectly showing an "apply from fork"
			// button in the user interface.
			throw new Error(`Remote ${sameUrlRemote.name} with url ${sameUrlRemote.url} already exists.`);
		}

		return await this.backend.invoke<string>("add_remote", { projectId, name, url });
	}
}

View on GitHub (pinned to 58e5313667)