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
- Regenerate the pseudo-version with the current toolchain: `go get <module>@<full-hash>` then copy the version string the tool writes into go.mod.
- Ensure the local/CI git uses the default short-hash abbreviation when deriving versions.
- 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
- Never hand-write the hash portion of a pseudo-version; let `go get @<commit>` produce it.
- Keep git's `core.abbrev` at the default so short hashes stay canonical.
- When upgrading toolchains, re-derive old pseudo-versions if the default abbrev changed.
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
- revision is shorter than canonical (expected %s)
- does not match short name of revision (expected %s)
- does not match version-control timestamp (expected %s)
- preceding tag (%s) not found
- not a descendent of preceding tag (%s)
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/30bf488957e8a02a.
Report an issue: GitHub.