gitbutlerapp/gitbutler · error · Error

Failed to add project after cloning.

Error message

Failed to add project after cloning.

What it means

Thrown by the onboarding clone flow after gitService.cloneRepo() succeeded but projectsService.addProject(targetDir) returned a falsy outcome. addProject returning null/undefined means the backend declined to register the freshly cloned directory as a GitButler project, so the clone is orphaned on disk.

Source

Thrown at apps/desktop/src/components/onboarding/CloneForm.svelte:90

		try {
			const remoteUrl = parseRemoteUrl(repositoryUrl);
			if (!remoteUrl) {
				return;
			}

			const targetDir = await backend.joinPath(targetDirPath, remoteUrl.name);

			await gitService.cloneRepo(repositoryUrl, targetDir);

			posthog.captureOnboarding(OnboardingEvent.ClonedProject);
			const outcome = await projectsService.addProject(targetDir);
			if (!outcome) {
				posthog.captureOnboarding(
					OnboardingEvent.ClonedProjectFailed,
					"Failed to add project after cloning",
				);
				throw new Error("Failed to add project after cloning.");
			}

			handleAddProjectOutcome(outcome, (project) => goto(projectPath(project.id)));
		} catch (e) {
			Sentry.captureException(e);
			const errorMessage = getErrorMessage(e);
			posthog.captureOnboarding(OnboardingEvent.ClonedProjectFailed, e);
			errors.push({
				label: errorMessage,
			});
		} finally {
			loading = false;
		}
	}

	function handleCancel() {
		if (history.length > 0) {
			history.back();

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Verify the cloned directory on disk contains a valid .git and at least one commit; clone a non-empty ref if the repo was empty.
  2. Retry adding the folder manually through the normal 'Add existing project' flow.
  3. Check the backend logs for the specific reason addProject refused the path.
  4. Ensure the target path is writable local storage, not a network/synced mount.

Example fix

// before
const outcome = await projectsService.addProject(targetDir);
if (!outcome) {
  throw new Error("Failed to add project after cloning.");
}

// after
const outcome = await projectsService.addProject(targetDir);
if (!outcome) {
  errors.push({
    label: "Cloned the repository but could not add it — add the folder manually from the project list",
  });
  return;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const targetDir = await backend.joinPath(targetDirPath, remoteUrl.name);
const hasGit = await backend.pathExists(`${targetDir}/.git`);
if (!hasGit) {
  errors.push({ label: "Clone did not produce a git repository at " + targetDir });
  return;
}
const outcome = await projectsService.addProject(targetDir);

Try / catch

try {
  const outcome = await projectsService.addProject(targetDir);
  if (!outcome) throw new Error("Failed to add project after cloning.");
} catch (e) {
  Sentry.captureException(e);
  errors.push({ label: getErrorMessage(e) });
}

Prevention

When it happens

Trigger: Any addProject call that comes back falsy: the cloned directory is not recognized as an adoptable repository (empty repo with no commits, odd worktree layout, nested .git), or the backend was not ready to accept project registration at that moment.

Common situations: Cloning a brand-new empty remote (no initial commit); target directory on a read-only or synced mount (Dropbox/OneDrive) confusing the scanner; joinPath produced an unexpected directory; racing app startup where the projects backend is still initializing.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/866ed670ff35f65a. Report an issue: GitHub.