argoproj/argo-workflows · error
failed to clone %q: %w
Error message
failed to clone %q: %w
What it means
This is the generic clone-failure wrap at workflow/artifacts/git/git.go:152. When git.PlainClone fails with anything other than transport.ErrEmptyRemoteRepository, Load returns 'failed to clone %q' wrapping the underlying go-git error. The real cause is always in the wrapped error: bad URL, auth failure, unknown revision/branch, TLS problems, or network errors.
Source
Thrown at workflow/artifacts/git/git.go:152
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)
}
}
w, err := r.Worktree()
if err != nil {
return fmt.Errorf("failed to get work tree: %w", err)
}View on GitHub (pinned to 35bff19146)
Solutions
- Read the wrapped inner error in the message — it names the actual cause (auth, not-found, TLS, network) and fixes differ per cause.
- For auth errors: verify the git secret (ssh-key format includes the 'PRIVATE KEY' header, correct username for HTTPS tokens) and that the secret is referenced correctly in the artifact.
- For not-found errors: test the URL with 'git ls-remote <url>' from an environment with the same credentials; fix typos or org renames.
- For TLS errors: set insecureSkipTLS: true (non-prod) or mount the CA cert into the executor and configure it.
- For Azure DevOps: confirm the workaround context — go-git cannot clone Azure DevOps repos while multi_ack capabilities are unsupported; keep the repo URL containing dev.azure.com so the driver applies its capability workaround.
Example fix
// before: artifact failing to authenticate
- git:
repo: https://github.com/my-org/private-repo.git
// after: supply credentials via secret
- git:
repo: https://github.com/my-org/private-repo.git
usernameSecret:
name: github-creds
key: username
passwordSecret:
name: github-creds
key: token Defensive patterns
Strategy: try-catch
Validate before calling
func precheckRepoReachable(repoURL string, creds *GitCreds) error {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
a := &wfv1.Artifact{ArtifactPaths: nil, Git: &wfv1.GitArtifact{Repo: repoURL}}
_ = a
run := exec.CommandContext(ctx, "git", "ls-remote", repoURL)
if creds != nil {
run.Env = append(os.Environ(), creds.Env()...)
}
out, err := run.CombinedOutput()
if err != nil {
return fmt.Errorf("repo %s unreachable: %v: %s", repoURL, err, out)
}
return nil
} Type guard
func isAuthErr(err error) bool {
var ar *transport.AuthError
return errors.As(err, &ar)
}
func isNotFoundErr(err error) bool {
return errors.Is(err, transport.ErrRepositoryNotFound)
} Try / catch
err := artifactDriver.Load(ctx, artifact, path)
if err != nil && strings.Contains(err.Error(), "failed to clone") {
inner := errors.Unwrap(errors.Unwrap(err))
switch {
case isAuthErr(inner):
return fmt.Errorf("check git credentials/secret: %w", err)
case isNotFoundErr(inner):
return fmt.Errorf("verify repo URL exists and is accessible: %w", err)
default:
// transient network issue: bounded retry
for i := 0; i < 3; i++ {
time.Sleep(time.Duration(1<<i) * time.Second)
if retryErr := artifactDriver.Load(ctx, artifact, path); retryErr == nil {
return nil
}
}
return err
}
} Prevention
- Verify the repo URL with 'git ls-remote' using the same credentials before deploying the workflow.
- Store SSH keys with the full 'BEGIN ... PRIVATE KEY' block in the secret; use correct usernames for HTTPS tokens.
- Test against an empty repo beforehand to know whether you will hit the empty-repo fallback vs clone path.
- For private CAs, mount the CA and configure it rather than blindly setting insecureSkipTLS.
- Watch go-git limitations (Azure DevOps multi_ack, shallow depth quirks) documented in the driver comments.
When it happens
Trigger: git.PlainClone(path, false, cloneOptions) in ArtifactDriver.Load fails for any non-empty-repo reason: unreachable host, authentication rejected (SSH key/HTTPS token), repository not found, TLS certificate verification failure, or the target path already containing a non-empty git repository.
Common situations: Wrong or renamed repo URL in the workflow spec; missing or expired git credentials (sshPrivateKey secret, HTTPS token); private repos without credentials; self-signed/ corporate CA certificates without insecureSkipTLS or the CA mounted; Azure DevOps repos hitting go-git capability issues; shallow depth=0 combined with unsupported refs.
Related errors
- unable to download blob %s: %w
- failed to plain init: %w
- failed to create remote %q: %w
- failed to create branch %q: %w
- failed to validate fetch %v: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/ad1f87e7c4b4ea58.
Report an issue: GitHub.