argoproj/argo-workflows · error

failed to plain init: %w

Error message

failed to plain init: %w

What it means

This error is produced by Argo Workflows' git artifact driver (workflow/artifacts/git/git.go:138) when it handles a remote repository that reported itself as empty. go-git's PlainClone returns transport.ErrEmptyRemoteRepository, so the driver falls back to git.PlainInit to create a fresh local repository at the artifact path. The wrap means the fallback PlainInit call itself failed (e.g. the directory already contains a git repo or is unwritable), so the artifact could not be set up at all.

Source

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

		Auth:            auth,
		Depth:           depth,
		SingleBranch:    a.SingleBranch,
		InsecureSkipTLS: g.InsecureSkipTLS,
	}
	if a.SingleBranch && a.Branch == "" {
		return errors.New("single branch mode without a branch specified")
	}
	if a.SingleBranch {
		cloneOptions.ReferenceName = plumbing.NewBranchReferenceName(a.Branch)
	}

	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 {

View on GitHub (pinned to 35bff19146)

Solutions

  1. Check the wrapped initErr: if it is git.ErrRepositoryAlreadyExists or 'repository already exists', delete the .git directory (or the whole artifact path) before retrying the step.
  2. Verify the artifact path volume is writable by the workflow pod's user; fix the volume mount or securityContext if not.
  3. If the repo is genuinely empty, that is unusual — push at least one commit (or an initial branch) to the source repo so PlainClone succeeds normally.
  4. If a prior run crashed mid-clone, use a fresh/empty emptyDir or clean the persistent volume between retries.

Example fix

// before: retrying into a dirty path fails with 'repository already exists'
r, initErr = git.PlainInit(path, false)
// after: clear leftover state first
if _, statErr := os.Stat(filepath.Join(path, ".git")); statErr == nil {
    os.RemoveAll(filepath.Join(path, ".git"))
}
r, initErr = git.PlainInit(path, false)
Defensive patterns

Strategy: validation

Validate before calling

func ensureCleanTarget(path string) error {
	if _, err := os.Stat(filepath.Join(path, ".git")); err == nil {
		return fmt.Errorf("%s already contains a git repository; clean it before loading the artifact", path)
	}
	f, err := os.CreateTemp(path, ".write-test")
	if err != nil {
		return fmt.Errorf("artifact path %s is not writable: %w", path, err)
	}
	f.Close()
	os.Remove(f.Name())
	return nil
}

Type guard

func isRepoExistsErr(err error) bool {
	return errors.Is(err, git.ErrRepositoryAlreadyExists)
}

Try / catch

err := artifactDriver.Load(ctx, artifact, path)
if err != nil && strings.Contains(err.Error(), "failed to plain init") {
	if isRepoExistsErr(errors.Unwrap(err)) {
		os.RemoveAll(filepath.Join(path, ".git"))
		err = artifactDriver.Load(ctx, artifact, path)
	}
}
if err != nil {
	return fmt.Errorf("git artifact load failed: %w", err)
}

Prevention

When it happens

Trigger: git.PlainInit(path, false) fails during the empty-repository fallback path of ArtifactDriver.Load — typically because the target path already contains an existing .git directory (PlainInit returns git.ErrRepositoryAlreadyExists), the path is not writable, or a previous partial clone left state behind.

Common situations: Cloning a git artifact pointing at a brand-new/empty repo (e.g. a fresh branch with zero commits); retrying a workflow step into a volume where a previous failed init left a .git directory; mounting the artifact path read-only; using the same path for two artifacts.

Related errors


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