golang/go · error

revision is longer than canonical (expected %s)

Error message

revision is longer than canonical (expected %s)

What it means

validatePseudoVersion (coderepo.go:694-703) compares the commit hash embedded in a pseudo-version against info.Short, the VCS's canonical short revision name. This branch fires when the embedded rev is a string that starts with info.Short — i.e. the pseudo-version carries a longer-than-canonical hash. Canonical short names are what `git rev-parse --short` yields; embedding extra hex digits makes the spelling non-canonical and wastes cache keys, so it is rejected.

Source

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

	defer func() {
		if err != nil {
			if _, ok := err.(*module.ModuleError); !ok {
				if _, ok := err.(*module.InvalidVersionError); !ok {
					err = &module.InvalidVersionError{Version: version, Pseudo: true, Err: err}
				}
				err = &module.ModuleError{Path: r.modPath, Err: err}
			}
		}
	}()

	rev, err := module.PseudoVersionRev(version)
	if err != nil {
		return err
	}
	if rev != info.Short {
		switch {
		case strings.HasPrefix(rev, info.Short):
			return fmt.Errorf("revision is longer than canonical (expected %s)", info.Short)
		case strings.HasPrefix(info.Short, rev):
			return fmt.Errorf("revision is shorter than canonical (expected %s)", info.Short)
		default:
			return fmt.Errorf("does not match short name of revision (expected %s)", info.Short)
		}
	}

	t, err := module.PseudoVersionTime(version)
	if err != nil {
		return err
	}
	if !t.Equal(info.Time.Truncate(time.Second)) {
		return fmt.Errorf("does not match version-control timestamp (expected %s)", info.Time.UTC().Format(module.PseudoVersionTimestampFormat))
	}

	tagPrefix := ""
	if r.codeDir != "" {
		tagPrefix = r.codeDir + "/"

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Regenerate the pseudo-version with the current toolchain: `go get <module>@<full-hash>` then copy the version string the tool writes into go.mod.
  2. Ensure the local/CI git uses the default short-hash abbreviation when deriving versions.
  3. If you must hand-build, extract the short hash via `git rev-parse --short <commit>` and embed exactly that.

Example fix

// before (40-char hash embedded)
require example.com/m v0.0.0-20240101120000-e3702bed3d42e03e85e3a1e6b1a5a3d2

// after (canonical 12-char short hash)
require example.com/m v0.0.0-20240101120000-e3702bed3d42
Defensive patterns

Strategy: validation

Validate before calling

// Validate a pseudo-version's rev field matches the VCS short hash.
// bash:
//   short=$(git rev-parse --short <commit>)
//   # ensure the pseudo-version embeds exactly $short
//
// Go:
package main
import ("fmt"; "golang.org/x/mod/module")
func check(pseudo string) error {
    rev, err := module.PseudoVersionRev(pseudo)
    if err != nil { return err }
    // compare rev against `git rev-parse --short` of the intended commit
    fmt.Println("embedded rev:", rev)
    return nil
}

Prevention

When it happens

Trigger: A pseudo-version was constructed by hand or by an older/different tool using a full 40-char (or non-default-length) hash while the VCS reports a shorter short-name. Also when a repo's core.abbrev setting changes the default short-hash length after a pseudo-version was recorded.

Common situations: Copy-pasting a full commit hash into a go.mod; switching git's `core.abbrev` from default to a larger value; pseudo-versions generated by tooling that predates the canonical-short enforcement.

Related errors


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