golang-migrate/migrate · error

duplicate migration version: %s

Error message

duplicate migration version: %s

What it means

createCmd checks the target migrations directory for any file matching `<version>_*<ext>` before writing new files. If a migration with the computed version (sequence or timestamp) already exists, creation is aborted to prevent two distinct migrations sharing one version, which would make ordering and the versions table ambiguous.

Source

Thrown at internal/cli/commands.go:114

			return err
		}
	} else {
		version, err = timeVersion(startTime, format)

		if err != nil {
			return err
		}
	}

	versionGlob := filepath.Join(dir, version+"_*"+ext)
	matches, err := filepath.Glob(versionGlob)

	if err != nil {
		return err
	}

	if len(matches) > 0 {
		return fmt.Errorf("duplicate migration version: %s", version)
	}

	if err = os.MkdirAll(dir, os.ModePerm); err != nil {
		return err
	}

	for _, direction := range []string{"up", "down"} {
		basename := fmt.Sprintf("%s_%s.%s%s", version, name, direction, ext)
		filename := filepath.Join(dir, basename)

		if err = createFile(filename); err != nil {
			return err
		}

		if print {
			absPath, _ := filepath.Abs(filename)
			log.Println(absPath)
		}

View on GitHub (pinned to 01a9643f14)

Solutions

  1. Wait/re-run so a new timestamp version is generated, or use `-seq` mode so versions auto-increment.
  2. Check the directory for a file starting with the reported version and delete/rename it if it is a leftover or duplicate.
  3. In seq mode, ensure existing migration files are present so the glob sees the max sequence before creating a new one.
  4. Use unique migration names and commit migration files together to avoid colliding versions across machines.

Example fix

// before (collides)
20260902120000_add_users.up.sql  <- exists, creating same version again
// after
run `migrate create -seq ...` -> 000003_add_users.up.sql
Defensive patterns

Strategy: validation

Validate before calling

versionGlob := filepath.Join(dir, version+"_*"+ext)
if matches, _ := filepath.Glob(versionGlob); len(matches) > 0 {
    return fmt.Errorf("version %s already exists: %v", version, matches)
}

Try / catch

if err := createCmd(...); err != nil {
    var dup string
    if _, scan := fmt.Sscanf(err.Error(), "duplicate migration version: %s", &dup); scan == nil {
        // resolve conflict: pick new version or remove stale file
    }
    return err
}

Prevention

When it happens

Trigger: `migrate create` when a file with the same version prefix already exists — e.g. creating two seq migrations without committing files so the sequence does not advance, or two `create` calls within the same timestamp granularity in non-seq (time) mode.

Common situations: Running `migrate create` twice in the same second with default timestamp format; a teammate already created version 5 but you pulled only part of the branch; CI reruns that recreate migrations into a shared directory.

Related errors


AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02). Data as JSON: /api/errors/e67b4049bc723c6e. Report an issue: GitHub.