golang/go · error

missing %s/go.mod and ...%s/go.mod at revision %s

Error message

missing %s/go.mod and ...%s/go.mod at revision %s

What it means

findDir (coderepo.go:910-914). Neither go.mod was found (err1 was NotExist, no major-subdir branch applied or file2 empty), the root-level implicit-go.mod fallback at line 905-908 did not apply (codeDir non-empty OR pathMajor is a real /vN suffix), and file2 was being tracked (the v2 layout would have been considered). Both `<pathPrefix>/go.mod` AND `.../<pathMajor>/go.mod` are missing at the revision. The module simply is not present in the repo at that revision.

Source

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

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

// isMajor reports whether the versions allowed for mpath are compatible with
// the major version(s) implied by pathMajor, or false if mpath has an invalid
// version suffix.
func isMajor(mpath, pathMajor string) bool {
	if mpath == "" {
		// If we don't have a path, we don't know what version(s) it is compatible with.
		return false
	}
	_, mpathMajor, ok := module.SplitPathVersion(mpath)
	if !ok {
		// An invalid module path is not compatible with any version.
		return false
	}
	if pathMajor == "" {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Create the missing go.mod in the source repo (root or /vN subdirectory) at the target revision.
  2. Use a version that actually has a go.mod (`go list -m -versions <module>`).
  3. For replace directives, point at a local directory or fork that contains the proper go.mod.
  4. If v2 is not yet released, depend on v1 or on a pseudo-version derived from a commit that has the file.

Example fix

// before: repo has neither go.mod nor v2/go.mod at v2.0.0 tag
//   $ go get example.com/m/v2@v2.0.0
//   missing example.com/m/go.mod and .../v2/go.mod at revision v2.0.0

// after: create v2/go.mod in source repo
//   v2/go.mod:
//     module example.com/m/v2
//     go 1.21
//   then re-tag and resolve
Defensive patterns

Strategy: validation

Validate before calling

// Ensure at least one go.mod exists at the target revision.
// bash:
//   git ls-tree -r --name-only <rev> | grep -E '(^|/)go.mod$|/v[0-9]+/go.mod$'
//   # if empty, create one before tagging
//
// For a v2 module, confirm v2/go.mod exists:
//   git cat-file -e <rev>:v2/go.mod || echo 'missing v2/go.mod'

Prevention

When it happens

Trigger: Resolving a major-versioned module (/v2) at a revision where neither root go.mod nor /v2/go.mod exists. Common right after a major bump before either file is committed, or for revisions older than the module's introduction.

Common situations: Tagging a /v2 version before creating /v2/go.mod; requesting a v2 of a module that has not yet been migrated; pointing replace at a fork that lacks the major-subdir go.mod; old tags predating go.mod adoption.

Related errors


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