{"record":{"id":"e67b4049bc723c6e","repo":"golang-migrate/migrate","slug":"duplicate-migration-version-s","errorCode":null,"errorMessage":"duplicate migration version: %s","messagePattern":"duplicate migration version: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cli/commands.go","lineNumber":114,"sourceCode":"\t\t\treturn err\n\t\t}\n\t} else {\n\t\tversion, err = timeVersion(startTime, format)\n\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tversionGlob := filepath.Join(dir, version+\"_*\"+ext)\n\tmatches, err := filepath.Glob(versionGlob)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif len(matches) > 0 {\n\t\treturn fmt.Errorf(\"duplicate migration version: %s\", version)\n\t}\n\n\tif err = os.MkdirAll(dir, os.ModePerm); err != nil {\n\t\treturn err\n\t}\n\n\tfor _, direction := range []string{\"up\", \"down\"} {\n\t\tbasename := fmt.Sprintf(\"%s_%s.%s%s\", version, name, direction, ext)\n\t\tfilename := filepath.Join(dir, basename)\n\n\t\tif err = createFile(filename); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif print {\n\t\t\tabsPath, _ := filepath.Abs(filename)\n\t\t\tlog.Println(absPath)\n\t\t}","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/internal/cli/commands.go#L96-L132","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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."],"exampleFix":"// before (collides)\n20260902120000_add_users.up.sql  <- exists, creating same version again\n// after\nrun `migrate create -seq ...` -> 000003_add_users.up.sql","handlingStrategy":"validation","validationCode":"versionGlob := filepath.Join(dir, version+\"_*\"+ext)\nif matches, _ := filepath.Glob(versionGlob); len(matches) > 0 {\n    return fmt.Errorf(\"version %s already exists: %v\", version, matches)\n}","typeGuard":null,"tryCatchPattern":"if err := createCmd(...); err != nil {\n    var dup string\n    if _, scan := fmt.Sscanf(err.Error(), \"duplicate migration version: %s\", &dup); scan == nil {\n        // resolve conflict: pick new version or remove stale file\n    }\n    return err\n}","preventionTips":["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."],"tags":["cli","migrations","duplicate","versioning"],"backgroundTag":"duplicate-migration-version","analyzedSha":"01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a","analyzedAt":"2026-09-02T19:38:29.671Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}