golang/go · error

%s has non-...%s module path %q%s at revision %s

Error message

%s has non-...%s module path %q%s at revision %s

What it means

findDir (coderepo.go:896-898). The root go.mod (file1) was read, declares a non-empty module path (mpath1), but pathMajor is non-empty (gopkg.in-style .vN suffix) and isMajor(mpath1, pathMajor) is false — the declared path's major-version suffix does not match the expected pathMajor. This branch is specific to gopkg.in-style major suffixes.

Source

Thrown at src/cmd/go/internal/modfetch/coderepo.go:897

		}
	}

	// Not v2/go.mod, so it's either go.mod or nothing. Which is it?
	if found1 {
		// Explicit go.mod with matching major version ok.
		return rev, r.codeDir, gomod1, nil
	}
	if err1 == nil {
		// Explicit go.mod with non-matching major version disallowed.
		suffix := ""
		if file2 != "" {
			suffix = fmt.Sprintf(" (and ...%s/go.mod does not exist)", r.pathMajor)
		}
		if mpath1 == "" {
			return "", "", nil, fmt.Errorf("%s is missing module path%s at revision %s", file1, suffix, rev)
		}
		if r.pathMajor != "" { // ".v1", ".v2" for gopkg.in
			return "", "", nil, fmt.Errorf("%s has non-...%s module path %q%s at revision %s", file1, r.pathMajor, mpath1, suffix, rev)
		}
		if _, _, ok := module.SplitPathVersion(mpath1); !ok {
			return "", "", nil, fmt.Errorf("%s has malformed module path %q%s at revision %s", file1, mpath1, suffix, rev)
		}
		return "", "", nil, fmt.Errorf("%s has post-%s module path %q%s at revision %s", file1, semver.Major(version), mpath1, suffix, rev)
	}

	if r.codeDir == "" && (r.pathMajor == "" || strings.HasPrefix(r.pathMajor, ".")) {
		// Implicit go.mod at root of repo OK for v0/v1 and for gopkg.in.
		return rev, "", nil, nil
	}

	// Implicit go.mod below root of repo or at v2+ disallowed.
	// Be clear about possibility of using either location for v2+.
	if file2 != "" {
		return "", "", nil, fmt.Errorf("missing %s/go.mod and ...%s/go.mod at revision %s", r.pathPrefix, r.pathMajor, rev)
	}
	return "", "", nil, fmt.Errorf("missing %s/go.mod at revision %s", r.pathPrefix, rev)

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Align the module path in go.mod with the major version implied by the import path (e.g. for gopkg.in/foo.v2 the go.mod must say `module gopkg.in/foo.v2`).
  2. If using replace, ensure the replacement path's major suffix matches.
  3. Tag and re-resolve.

Example fix

// before: go.mod
//   module gopkg.in/foo.v3
//
// import path requested: gopkg.in/foo.v2

// after: go.mod
//   module gopkg.in/foo.v2
Defensive patterns

Strategy: validation

Validate before calling

// For gopkg.in modules, the go.mod module path must match the import path's major.
// bash:
//   # import path gopkg.in/foo.v2 -> go.mod must say 'module gopkg.in/foo.v2'
//   grep -H '^module ' go.mod
// Cross-check:
//   expected='gopkg.in/foo.v2'
//   grep -qE "^module ${expected}$" go.mod || echo 'gopkg.in major mismatch'

Prevention

When it happens

Trigger: Resolving a gopkg.in module (pathMajor like .v2) where the root go.mod declares a module path with a different major-version suffix (e.g. `module gopkg.in/foo.v3` while pathMajor expects .v2).

Common situations: gopkg.in modules whose go.mod was edited to point at a different major version than the import path; forked gopkg.in modules with mismatched suffixes; replace directives that mis-route gopkg.in paths.

Related errors


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