golang/go · error

does not match version-control timestamp (expected %s)

Error message

does not match version-control timestamp (expected %s)

What it means

validatePseudoVersion (coderepo.go:705-711) parses the UTC timestamp encoded in the pseudo-version and compares it (to the second) against info.Time from the VCS. A mismatch means the timestamp in the version string lies about when the commit was made. The timestamp is load-bearing for version ordering, so a wrong timestamp would let authors artificially inflate precedence — hence the strict check.

Source

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

		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 + "/"
	}

	// A pseudo-version should have a precedence just above its parent revisions,
	// and no higher. Otherwise, it would be possible for library authors to "pin"
	// dependency versions (and bypass the usual minimum version selection) by
	// naming an extremely high pseudo-version rather than an accurate one.
	//
	// Moreover, if we allow a pseudo-version to use any arbitrary pre-release
	// tag, we end up with infinitely many possible names for each commit. Each
	// name consumes resources in the module cache and proxies, so we want to
	// restrict them to a finite set under control of the module author.
	//
	// We address both of these issues by requiring the tag upon which the

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Let the toolchain derive the pseudo-version: `go get <module>@<commit>` — it reads the commit time from the VCS and formats it correctly.
  2. If constructing manually, use `git log -1 --format=%cI <commit>` to get the UTC timestamp and the format `YYYYMMDDHHMMSS`.
  3. After upstream rebases that alter commit times, refresh affected pseudo-versions.

Example fix

// before (timestamp does not match commit)
require example.com/m v0.0.0-20231231235959-e3702bed3d42

// after (use the commit's actual UTC time)
require example.com/m v0.0.0-20240101120000-e3702bed3d42
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the timestamp matches the commit's UTC time.
// bash:
//   ts=$(git log -1 --format=%cI <commit> | date -u +%Y%m%d%H%M%S)
//   # the pseudo-version must contain this exact timestamp
//
// Go:
package main
import ("time"; "golang.org/x/mod/module")
func validateTs(pseudo string, commitTime time.Time) error {
    t, err := module.PseudoVersionTime(pseudo)
    if err != nil { return err }
    if !t.Equal(commitTime.Truncate(time.Second)) {
        return fmt.Errorf("timestamp mismatch: pseudo=%s commit=%s", t, commitTime)
    }
    return nil
}

Prevention

When it happens

Trigger: Hand-building a pseudo-version with an invented or rounded timestamp; timezone mishandling when constructing the UTC timestamp; a VCS reports commit time in a non-UTC zone and the constructor didn't convert.

Common situations: Generating pseudo-versions with `date -u` but wrong format string; rebases that change commit timestamps; pseudo-versions built before the toolchain enforced the canonical timestamp format.

Related errors


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