golang/go · error

reading %s/%s at revision %s: %v

Error message

reading %s/%s at revision %s: %v

What it means

findDir (coderepo.go:842-846) reads go.mod at r.codeDir/go.mod (the root or subdirectory go.mod) at the resolved revision. err1 was a real I/O failure (not os.IsNotExist) — e.g. network error, auth failure, corrupt object, repository unreachable. The error is wrapped with the codeRoot, file path, and revision for diagnostics.

Source

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

	return r.revToRev(version), nil
}

// findDir locates the directory within the repo containing the module.
//
// If r.pathMajor is non-empty, this can be either r.codeDir or — if a go.mod
// file exists — r.codeDir/r.pathMajor[1:].
func (r *codeRepo) findDir(ctx context.Context, version string) (rev, dir string, gomod []byte, err error) {
	rev, err = r.versionToRev(version)
	if err != nil {
		return "", "", nil, err
	}

	// Load info about go.mod but delay consideration
	// (except I/O error) until we rule out v2/go.mod.
	file1 := path.Join(r.codeDir, "go.mod")
	gomod1, err1 := r.code.ReadFile(ctx, rev, file1, codehost.MaxGoMod)
	if err1 != nil && !os.IsNotExist(err1) {
		return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.codeRoot, file1, rev, err1)
	}
	mpath1 := modfile.ModulePath(gomod1)
	found1 := err1 == nil && (isMajor(mpath1, r.pathMajor) || r.canReplaceMismatchedVersionDueToBug(mpath1))

	var file2 string
	if r.pathMajor != "" && r.codeRoot != r.modPath && !strings.HasPrefix(r.pathMajor, ".") {
		// Suppose pathMajor is "/v2".
		// Either go.mod should claim v2 and v2/go.mod should not exist,
		// or v2/go.mod should exist and claim v2. Not both.
		// Note that we don't check the full path, just the major suffix,
		// because of replacement modules. This might be a fork of
		// the real module, found at a different path, usable only in
		// a replace directive.
		dir2 := path.Join(r.codeDir, r.pathMajor[1:])
		file2 = path.Join(dir2, "go.mod")
		gomod2, err2 := r.code.ReadFile(ctx, rev, file2, codehost.MaxGoMod)
		if err2 != nil && !os.IsNotExist(err2) {
			return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.codeRoot, file2, rev, err2)

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Retry the fetch (`go mod download`); transient network errors often clear.
  2. For private repos, set GOPRIVATE=example.com and ensure credentials (.netrc, SSH key, GOPROXY=direct) are configured.
  3. Clear the module cache if corrupt: `go clean -modcache`.
  4. Inspect the wrapped %v for the underlying transport/VCS error and address it specifically.

Example fix

// before (private repo, no auth config)
// $ go get example.com/m@v1.2.3
// reading example.com/m/go.mod at revision v1.2.3: ... unauthorized

// after
// $ export GOPRIVATE=example.com
// $ export GOPROXY=direct
// $ go get example.com/m@v1.2.3
Defensive patterns

Strategy: retry

Validate before calling

// Configure environment before fetching private/VCS-backed modules.
// bash:
//   go env -w GOPRIVATE=example.com
//   go env -w GONOSUMCHECK=example.com
//   # ensure ~/.netrc or SSH keys are set for the VCS host
//   go env -w GOPROXY=direct   # if bypassing the proxy
//
// Then retry: go mod download

Try / catch

// Bash-style retry with backoff for transient transport errors.
// for i in 1 2 3; do go mod download && break || sleep $((i*i)); done
// Inspect the wrapped error after the final attempt; if auth-related, fix credentials rather than retrying.

Prevention

When it happens

Trigger: r.code.ReadFile against the VCS/proxy returned a transport error (timeout, 5xx, TLS, auth) while fetching the root go.mod. Distinct from 'file does not exist' which is handled separately.

Common situations: Private VCS requiring GOPRIVATE/GONOSUMCHECK or .netrc auth; flaky proxy (proxy.golang.org or ATHENS); broken SSH key for git-over-ssh; corrupt module cache entries; rate limiting.

Related errors


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