semaphoreui/semaphore · error
invalid migration version major part
Error message
invalid migration version major part %s
What it means
ParseVersion parses a migration version string in 'major[.minor][.patch]' form. When the major component cannot be converted to an integer with strconv.Atoi, it returns 'invalid migration version major part %s'. This is a fail-fast guard so migration ordering (via Compare) never operates on garbage versions.
Solutions
- Rename the migration version so the first segment is a plain integer, e.g. '1' or '1.0.0' instead of 'v1.0.0'
- Strip non-numeric characters (like a leading 'v') before passing the version string into Compare/ParseVersion
- Add a pre-commit/CI check that validates every migration version parses before it is committed
Example fix
// before
Compare("v1.2.0", "1.3.0")
// after
Compare("1.2.0", "1.3.0") Defensive patterns
Strategy: validation
Validate before calling
var versionRe = regexp.MustCompile(`^\d+(\.\d+)?(\.\d+)?$`)
func validMigrationVersion(v string) bool { return versionRe.MatchString(strings.TrimPrefix(v, "v")) } Try / catch
if err := Compare(a, b); err != nil {
if strings.Contains(err.Error(), "invalid migration version") {
log.Fatalf("bad migration version: %v", err)
}
return err
} Prevention
- Use plain numeric 'major[.minor][.patch]' version strings in migration filenames
- Strip 'v' prefixes and other decorations before parsing
- Add a CI check that parses every migration version
When it happens
Trigger: Calling Compare (which calls ParseVersion) with a migration whose Version's first dot-separated segment is non-numeric, e.g. 'v1.0.0', 'alpha.2', or '.3'.
Common situations: Hand-written migration filenames/versions that include a 'v' prefix, letters, or leading separators; renaming migration files without keeping numeric prefixes; scripts that generate versions from timestamps with non-numeric separators.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid migration version minor part
- invalid migration version patch part
- Failed to link external account.
- Internal Server Error
- no admins found in database; create a admin first
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/2e79cd105cdbc5ad.
Report an issue: GitHub.
Appendix: source
Thrown at db/Migration.go:168
type MigrationVersion struct {
Major int
Minor int
Patch int
}
func (m Migration) ParseVersion() (res MigrationVersion, err error) {
parts := strings.Split(m.Version, ".")
if len(parts) < 2 {
err = fmt.Errorf("invalid migration version format %s", m.Version)
return
}
res.Major, err = strconv.Atoi(parts[0])
if err != nil {
err = fmt.Errorf("invalid migration version major part %s", parts[0])
return
}
res.Minor, err = strconv.Atoi(parts[1])
if err != nil {
err = fmt.Errorf("invalid migration version minor part %s", parts[1])
return
}
if len(parts) < 3 {
res.Patch = math.MaxInt
return
}
res.Patch, err = strconv.Atoi(parts[2])
if err != nil {
err = fmt.Errorf("invalid migration version patch part %s", parts[2])
returnView on GitHub (pinned to 1774ccb71a)