golang/go · error

invalid version control suffix in %s path

Error message

invalid version control suffix in %s path

What it means

noVCSSuffix rejects an import path whose repository component ends in a VCS command suffix (e.g. '.git', '.hg'). The %s is the matched prefix. This prevents ambiguous paths like 'host/foo.git/sub' that would otherwise be parsed as a VCS-suffixed repo.

Source

Thrown at src/cmd/go/internal/vcs/vcs.go:1317

		repo:       "https://{root}",
	},

	// General syntax for any server.
	// Must be last.
	{
		regexp:         lazyregexp.New(`(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?(/~?[\w.\-]+)+?)\.(?P<vcs>fossil|git|hg|svn))(/~?[\w.\-]+)*$`),
		schemelessRepo: true,
	},
}

// noVCSSuffix checks that the repository name does not
// end in .foo for any version control system foo.
// The usual culprit is ".git".
func noVCSSuffix(match map[string]string) error {
	repo := match["repo"]
	for _, vcs := range vcsList {
		if strings.HasSuffix(repo, "."+vcs.Cmd) {
			return fmt.Errorf("invalid version control suffix in %s path", match["prefix"])
		}
	}
	return nil
}

// importError is a copy of load.importError, made to avoid a dependency cycle
// on cmd/go/internal/load. It just needs to satisfy load.ImportPathError.
type importError struct {
	importPath string
	err        error
}

func importErrorf(path, format string, args ...any) error {
	err := &importError{importPath: path, err: fmt.Errorf(format, args...)}
	if errStr := err.Error(); !strings.Contains(errStr, path) {
		panic(fmt.Sprintf("path %q not in error %q", path, errStr))
	}
	return err

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Drop the VCS suffix from the import path (use 'example.com/repo' not 'example.com/repo.git')
  2. For GitHub, use the plain module path without .git

Example fix

// before
import "example.com/repo.git/pkg"
// after
import "example.com/repo/pkg"
Defensive patterns

Strategy: type-guard

Type guard

// Reject import paths carrying a VCS suffix before resolving
func hasVCSSuffix(path string) bool {
  for _, s := range []string{".git", ".hg", ".svn", ".fossil", ".bzr"} {
    if strings.Contains(path, s+"/") || strings.HasSuffix(path, s) { return true }
  }
  return false
}

Prevention

When it happens

Trigger: Importing a path that matches the general server regexp with a trailing .<vcs>, e.g. 'example.com/repo.git/pkg'.

Common situations: User copy-pastes a clone URL including the .git extension; legacy gopkg.in-style paths with suffixes.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/083ca354245198a4. Report an issue: GitHub.