argoproj/argo-workflows · error

failed to validate fetch %v: %w

Error message

failed to validate fetch %v: %w

What it means

This error is raised at workflow/artifacts/git/git.go:161 when the git.FetchOptions built from the artifact's 'fetch' list fail go-git's opts.Validate(). Validation is a pure client-side check on the RefSpec strings (plus required fields like Remote/Force defaults), so this fires before any network I/O. It means one or more refspec strings are malformed or the options struct is inconsistent, not that the remote is broken.

Source

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

		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)
	}

	if a.Revision != "" {
		refSpecs := []config.RefSpec{"refs/heads/*:refs/heads/*"}
		if a.SingleBranch {
			refSpecs = []config.RefSpec{config.RefSpec(fmt.Sprintf("refs/heads/%s:refs/heads/%s", a.Branch, a.Branch))}
		}
		opts := &git.FetchOptions{Auth: auth, RefSpecs: refSpecs, InsecureSkipTLS: g.InsecureSkipTLS}
		if err := opts.Validate(); err != nil {
			return fmt.Errorf("failed to validate fetch %v: %w", refSpecs, err)

View on GitHub (pinned to 35bff19146)

Solutions

  1. Read the wrapped validateErr — go-git reports which refspec and why (e.g. 'invalid refspec').
  2. Fix each fetch entry to the [+]<src>:<dst> form with full ref paths, e.g. 'refs/heads/main:refs/heads/main' or 'refs/heads/*:refs/heads/*'.
  3. Remove empty or whitespace-only entries from artifact.git.fetch.
  4. If using depth (shallow clone), simplify the fetch refspecs to explicit branch refs and retest.
  5. Validate refspec strings locally with a tiny go-git snippet calling (&config.RefSpec(s)).Validate() before deploying the workflow.

Example fix

// before: malformed refspec fails validation
fetch:
  - heads/*
// after: full, valid refspec
fetch:
  - "refs/heads/*:refs/heads/*"
Defensive patterns

Strategy: validation

Validate before calling

var refSpecRe = regexp.MustCompile(`^(\+)?refs/[^\s]+(:refs/[^\s]+)?$`)

func validateFetchRefspecs(fetch []string) error {
	for _, spec := range fetch {
		if strings.TrimSpace(spec) == "" {
			return fmt.Errorf("empty fetch refspec")
		}
		rs := config.RefSpec(spec)
		if err := rs.Validate(); err != nil {
			return fmt.Errorf("invalid fetch refspec %q: %w", spec, err)
		}
		if !refSpecRe.MatchString(spec) {
			return fmt.Errorf("fetch refspec %q should look like [+]<src>:<dst> with full refs/ paths", spec)
		}
	}
	return nil
}

Type guard

func isValidRefSpec(s string) bool {
	rs := config.RefSpec(s)
	return rs.Validate() == nil
}

Try / catch

// client-side guard before submitting the workflow
if err := validateFetchRefspecs(artifact.Git.Fetch); err != nil {
	return fmt.Errorf("refusing to submit workflow: %w", err)
}
// at runtime, this error is deterministic: do NOT retry
if err != nil && strings.Contains(err.Error(), "failed to validate fetch") {
	return fmt.Errorf("fix artifact.git.fetch refspecs: %w", err)
}

Prevention

When it happens

Trigger: ArtifactDriver.Load builds git.FetchOptions{Auth, RefSpecs, Depth, InsecureSkipTLS} from artifact.git.fetch entries and calls opts.Validate(); validation fails because a refspec string is empty or syntactically invalid (go-git refspecs must look like [+]<src>[:<dst>] with valid wildcards, e.g. 'refs/heads/*:refs/heads/*'), or RefSpecs contain mutually inconsistent patterns.

Common situations: Typos in the artifact's fetch list (missing colon, stray spaces, bare '*'); using a plus '+refs/...' with a shallow Depth combination rejected by validation; hand-written wildcard refspecs like 'heads/*' without the refs/ prefix; copy-pasted refspecs from CLI git that go-git parses more strictly.

Related errors


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