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
- Wait/re-run so a new timestamp version is generated, or use `-seq` mode so versions auto-increment.
- Check the directory for a file starting with the reported version and delete/rename it if it is a leftover or duplicate.
- In seq mode, ensure existing migration files are present so the glob sees the max sequence before creating a new one.
- 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
- Prefer -seq mode so versions auto-increment and cannot collide within a second.
- Commit migration files promptly so teammates' versions are visible before you create new ones.
- Avoid CI jobs that generate migrations into a shared directory concurrently.
- Use unique, descriptive migration names.
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
- next sequence number %s too large, at most %d digits are all
- unable to parse file %v
- malformed migration filename: %s
- unable to parse file %v
- digits must be positive
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/e67b4049bc723c6e.
Report an issue: GitHub.