argoproj/argo-workflows · error

failed to create branch %q: %w

Error message

failed to create branch %q: %w

What it means

This error is raised at workflow/artifacts/git/git.go:148 in the empty-remote-repository fallback path. After PlainInit and CreateRemote, the driver creates a local branch named after the artifact's revision (defaulting to 'master') with r.CreateBranch, wired to track origin/master. The wrap means go-git's CreateBranch rejected the branch config — usually because a branch with that name already exists, the name is invalid, or the underlying reference write failed.

Source

Thrown at workflow/artifacts/git/git.go:148

	}

	r, err := git.PlainClone(path, false, cloneOptions)
	if errors.Is(err, transport.ErrEmptyRemoteRepository) {
		logging.RequireLoggerFromContext(ctx).Info(ctx, "Cloned an empty repository")
		var initErr error
		r, initErr = git.PlainInit(path, false)
		if initErr != nil {
			return fmt.Errorf("failed to plain init: %w", initErr)
		}
		if _, remoteErr := r.CreateRemote(&config.RemoteConfig{Name: git.DefaultRemoteName, URLs: []string{a.Repo}}); remoteErr != nil {
			return fmt.Errorf("failed to create remote %q: %w", a.Repo, remoteErr)
		}
		branchName := a.Revision
		if branchName == "" {
			branchName = "master"
		}
		if err = r.CreateBranch(&config.Branch{Name: branchName, Remote: git.DefaultRemoteName, Merge: plumbing.Master}); err != nil {
			return fmt.Errorf("failed to create branch %q: %w", branchName, err)
		}
		return nil
	} else if err != nil {
		return fmt.Errorf("failed to clone %q: %w", a.Repo, err)
	}
	if len(a.Fetch) > 0 {
		refSpecs := make([]config.RefSpec, len(a.Fetch))
		for i, spec := range a.Fetch {
			refSpecs[i] = config.RefSpec(spec)
		}
		opts := &git.FetchOptions{Auth: auth, RefSpecs: refSpecs, Depth: depth, InsecureSkipTLS: g.InsecureSkipTLS}
		if validateErr := opts.Validate(); validateErr != nil {
			return fmt.Errorf("failed to validate fetch %v: %w", refSpecs, validateErr)
		}
		if err = r.Fetch(opts); isFetchErr(err) {
			return fmt.Errorf("failed to fetch %v: %w", refSpecs, err)
		}
	}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Check the wrapped err: 'branch already exists' means leftover state — wipe the artifact path and retry the step.
  2. If a.Revision is a commit SHA or tag, note that this code only handles the empty-repo case; prefer pointing at a non-empty repo or a branch name.
  3. Ensure the revision string is a valid git branch name (no '..', no trailing '.lock', no invalid characters).
  4. Be aware the fallback tracks Merge: plumbing.Master even for non-master branchName; if your empty repo will use 'main', expect follow-up fetch oddities and push an initial commit to avoid this path entirely.

Example fix

// before
if err = r.CreateBranch(&config.Branch{Name: branchName, Remote: git.DefaultRemoteName, Merge: plumbing.Master}); err != nil {
// after: tolerate pre-existing branch from a previous attempt
if err = r.CreateBranch(&config.Branch{Name: branchName, Remote: git.DefaultRemoteName, Merge: plumbing.Master}); err != nil && !errors.Is(err, git.ErrBranchExists) {
    return fmt.Errorf("failed to create branch %q: %w", branchName, err)
}
Defensive patterns

Strategy: validation

Validate before calling

func validBranchName(name string) error {
	if name == "" {
		return nil // driver defaults to master
	}
	if strings.ContainsAny(name, " ~^:?*[\\\\") || strings.HasSuffix(name, ".lock") || strings.Contains(name, "..") {
		return fmt.Errorf("%q is not a valid git branch name", name)
	}
	return nil
}
// call before submitting: validBranchName(wfArtifact.Git.Revision)

Type guard

func isBranchExistsErr(err error) bool {
	return errors.Is(err, git.ErrBranchExists)
}

Try / catch

err := artifactDriver.Load(ctx, artifact, path)
if err != nil && strings.Contains(err.Error(), "failed to create branch") {
	if isBranchExistsErr(errors.Unwrap(err)) {
		os.RemoveAll(path) // clear stale branch state and retry
		err = artifactDriver.Load(ctx, artifact, path)
	}
}
if err != nil {
	return fmt.Errorf("git artifact load failed: %w", err)
}

Prevention

When it happens

Trigger: r.CreateBranch(&config.Branch{Name: branchName, Remote: git.DefaultRemoteName, Merge: plumbing.Master}) fails when loading a git artifact from an empty repository — duplicate branch name (ErrBranchExists), invalid branch name characters in a.Revision (e.g. a commit SHA or tag containing '/'), or a ref write error.

Common situations: Setting git.revision to a commit SHA or tag on an empty-looking repo — SHAs/tags are not valid branch names here; rerunning into a path that already has the branch; a repo where the default branch is 'main' but the fallback hardcodes Merge: plumbing.Master, causing tracking mismatches on later fetches.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/8807d41427c02019. Report an issue: GitHub.