golang/go · error
module paths beginning with gopkg.in/ must always have a maj
Error message
module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN: go mod init %s
What it means
During 'go mod init', the supplied module path starts with 'gopkg.in/' but module.SplitPathVersion could not extract a valid .vN major-version suffix. gopkg.in paths have a special rule: they MUST carry a .vN suffix. The message embeds a suggested path from suggestGopkgIn (which appends .v1 if no major was detected).
Source
Thrown at src/cmd/go/internal/modload/init.go:1269
func checkModulePath(modPath string) {
if err := module.CheckImportPath(modPath); err != nil {
if pathErr, ok := err.(*module.InvalidPathError); ok {
pathErr.Kind = "module"
// Same as build.IsLocalPath()
if pathErr.Path == "." || pathErr.Path == ".." ||
strings.HasPrefix(pathErr.Path, "./") || strings.HasPrefix(pathErr.Path, "../") {
pathErr.Err = errors.New("is a local import path")
}
}
base.Fatal(err)
}
if err := CheckReservedModulePath(modPath); err != nil {
base.Fatalf(`go: invalid module path %q: `, modPath)
}
if _, _, ok := module.SplitPathVersion(modPath); !ok {
if strings.HasPrefix(modPath, "gopkg.in/") {
invalidMajorVersionMsg := fmt.Errorf("module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN:\n\tgo mod init %s", suggestGopkgIn(modPath))
base.Fatalf(`go: invalid module path "%v": %v`, modPath, invalidMajorVersionMsg)
}
invalidMajorVersionMsg := fmt.Errorf("major version suffixes must be in the form of /vN and are only allowed for v2 or later:\n\tgo mod init %s", suggestModulePath(modPath))
base.Fatalf(`go: invalid module path "%v": %v`, modPath, invalidMajorVersionMsg)
}
}
// fixVersion returns a modfile.VersionFixer implemented using the Query function.
//
// It resolves commit hashes and branch names to versions,
// canonicalizes versions that appeared in early vgo drafts,
// and does nothing for versions that already appear to be canonical.
//
// The VersionFixer sets 'fixed' if it ever returns a non-canonical version.
func fixVersion(ld *Loader, ctx context.Context, fixed *bool) modfile.VersionFixer {
return func(path, vers string) (resolved string, err error) {
defer func() {
if err == nil && resolved != vers {View on GitHub (pinned to b6b368adc5)
Solutions
- Use the suggested command printed in the error, e.g. 'go mod init gopkg.in/user/project.v1'.
- Pick the major version explicitly: .v1, .v2, .v3 ... matching the library's actual major.
- If you do not need gopkg.in semantics, choose a normal domain path (example.com/project).
- Verify the path matches the upstream gopkg.in repository exactly.
Example fix
// before $ go mod init gopkg.in/yaml // module paths beginning with gopkg.in/ must always have a major version suffix ...: // go mod init gopkg.in/yaml.v1 // after $ go mod init gopkg.in/yaml.v3
Defensive patterns
Strategy: validation
Validate before calling
// Validate a gopkg.in path before 'go mod init'.
func validGopkgIn(p string) error {
if !strings.HasPrefix(p, "gopkg.in/") { return nil }
if _, _, ok := module.SplitPathVersion(p); !ok {
return fmt.Errorf("gopkg.in path needs .vN suffix, e.g. %s.v1", strings.TrimRight(p, "/"))
}
return nil
} Type guard
func isGopkgInWithMajor(p string) bool {
return strings.HasPrefix(p, "gopkg.in/") && func() bool {
_, _, ok := module.SplitPathVersion(p); return ok
}()
} Try / catch
out, err := exec.Command("go", "mod", "init", path).CombinedOutput()
if err != nil && bytes.Contains(out, []byte("gopkg.in/ must always have a major version suffix")) {
// use the suggestion embedded in the error message
suggested := extractSuggestedPath(out) // your helper parses the 'go mod init ...' hint
out, err = exec.Command("go", "mod", "init", suggested).CombinedOutput()
}
return err Prevention
- Always pass a .vN suffix for gopkg.in paths when running 'go mod init'.
- Cross-check the path against the upstream gopkg.in repository URL.
- Wrap 'go mod init' in a script that auto-suggests the .vN form.
- Document the gopkg.in convention for your team.
When it happens
Trigger: 'go mod init gopkg.in/user/project' (no .vN) while SplitPathVersion fails. The gopkg.in branch is taken and the user is told the canonical form via the suggestion.
Common situations: User unfamiliar with the gopkg.in convention; copying a GitHub-style path verbatim; migrating from dep/glide which did not enforce the suffix.
Related errors
- major version suffixes must be in the form of /vN and are on
- %s has non-...%s module path %q%s at revision %s
- invalid module path %q
- repository rooted at %s cannot contain module %s
- %s/%s has non-...%s module path %q at revision %s
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/8bcab2b260b2f6a5.
Report an issue: GitHub.