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
- Read the wrapped validateErr — go-git reports which refspec and why (e.g. 'invalid refspec').
- 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/*'.
- Remove empty or whitespace-only entries from artifact.git.fetch.
- If using depth (shallow clone), simplify the fetch refspecs to explicit branch refs and retest.
- 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
- Always write refspecs in full [+]<src>:<dst> form with refs/ prefixes.
- Lint fetch entries with go-git's RefSpec.Validate in CI before submitting workflows.
- Strip empty/whitespace entries from artifact.git.fetch lists.
- Avoid mixing shallow depth with complex wildcard refspecs unless tested.
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
- malformed workflow template parameter "%s": valueFrom is nil
- maxRetries cannot be less than 0
- baseDelay cannot be less than 0
- maxDelay cannot be less than 0
- retryMultiple cannot be less than 0
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/7fec6d3e1e7a7209.
Report an issue: GitHub.