semaphoreui/semaphore · error

invalid migration version format

Error message

invalid migration version format %s

What it means

Migration.ParseVersion splits the Version string on '.' and requires at least two parts (major.minor) to build a comparable MigrationVersion. Versions with no dot — or empty strings reaching the parser — are rejected with this formatted error, surfaced through Compare when ordering migrations.

Solutions

  1. Rename/redefine the migration version to include both major and minor parts (e.g. "1.0", "3.2")
  2. Audit migration file names and the Version fields produced by the loader for missing dot separators
  3. Keep versions strictly in major.minor (optionally patch) format matching the project's existing migration history

Example fix

// before
// migration file: 5__add_table.sql  -> Version "5"
// after
// migration file: 5.0__add_table.sql -> Version "5.0"
Defensive patterns

Strategy: validation

Validate before calling

if len(strings.Split(m.Version, ".")) < 2 {
	return fmt.Errorf("version %q must be in major.minor format", m.Version)
}

Type guard

func isDottedVersion(v string) bool {
	return len(strings.Split(v, ".")) >= 2
}

Try / catch

if _, err := m.ParseVersion(); err != nil {
	if strings.Contains(err.Error(), "invalid migration version format") {
		return fmt.Errorf("bad migration version: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Comparing or sorting migrations whose Version lacks a '.', e.g. "1", "v2", "" (when Validate was skipped), or a version accidentally stripped of its minor part by string processing.

Common situations: Hand-edited migration versions like "3" instead of "3.0"; scripts renaming migration files and dropping part of the version; mixing migration sets from forks using different versioning schemes.

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


AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07). Data as JSON: /api/errors/2ced26106ef4344b. Report an issue: GitHub.

Appendix: source

Thrown at db/Migration.go:162

	if m.Version == "" {
		return fmt.Errorf("migration version is empty")
	}

	return nil
}

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

View on GitHub (pinned to 1774ccb71a)