hasura/graphql-engine · error
found duplicate migrations for version %d - %s - %s
Error message
found duplicate migrations for version %d - %s - %s
What it means
Returned by source.Migrations.Append (used while scanning the migrations directory) when two migration files claim the same version number and the same direction. The CLI indexes migrations by version+direction, so a duplicate makes rollback/apply ambiguous and is rejected, listing both conflicting file names.
Source
Thrown at cli/migrate/source/migration.go:71
Migrations: make(map[uint64]map[Direction]*Migration),
}
}
func (i *Migrations) Append(m *Migration) (err error) {
var op errors.Op = "source.Migrations.Append"
if m == nil {
return errors.E(op, stderrors.New("migration cannot be nill"))
}
if i.Migrations[m.Version] == nil {
i.Migrations[m.Version] = make(map[Direction]*Migration)
}
// reject duplicate versions
if migration, dup := i.Migrations[m.Version][m.Direction]; dup {
return errors.E(
op,
fmt.Errorf(
"found duplicate migrations for version %d\n- %s\n- %s",
m.Version,
m.Raw,
migration.Raw,
),
)
}
i.Migrations[m.Version][m.Direction] = m
i.buildIndex()
return nil
}
func (i *Migrations) buildIndex() {
i.Index = make(uint64Slice, 0)
for version := range i.Migrations {
i.Index = append(i.Index, version)View on GitHub (pinned to 724551b9ae)
Solutions
- Rename one of the two files listed in the error to the next unused version number (both its .up and .down files)
- If both are equivalent, delete one of them
- Going forward, generate migrations with `hasura migrate create` so versions are allocated sequentially
- After fixing, re-run `hasura migration status` to confirm a clean scan
Example fix
# before migrations/12_create_table.up.yaml migrations/12_add_users.up.sql # duplicate version 12 # after migrations/12_create_table.up.yaml migrations/13_add_users.up.sql # bump to unused version
Defensive patterns
Strategy: validation
Validate before calling
// Pre-scan for duplicate versions before running migrations
seen := map[int64]bool{}
entries, _ := os.ReadDir("migrations")
for _, e := range entries {
parts := strings.SplitN(e.Name(), "_", 2)
if v, err := strconv.ParseInt(parts[0], 10, 64); err == nil {
if seen[v] { return fmt.Errorf("duplicate version %d", v) }
seen[v] = true
}
} Try / catch
if err := src.Scan(); err != nil {
if strings.Contains(err.Error(), "found duplicate migrations") {
// renumber one of the listed files
}
} Prevention
- Generate migrations only via `hasura migrate create`
- Review migrations directory in code review for version collisions after merges
- Keep both .up and .down files for a version together
When it happens
Trigger: Having two files like 12_create_table.up.yaml and 12_add_users.up.sql in migrations/ — same version 12, same direction (up or down), regardless of extension or name suffix; triggered by NewMigrate/Scan or any migrate command that reads the source.
Common situations: Copy-pasting a migration file and editing it instead of generating a new one; two developers creating migrations independently and merging branches; mixing .sql and .yaml for the same version; renaming files so versions collide.
Related errors
- error removing migrations from project: %w
- unable to delete migrations from project for: %v : %w
- unable to move migrations from project for: %v : %w
- cannot read file %s: %w
- operation failed: %w
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/d4541abbb3421ec2.
Report an issue: GitHub.