golang-migrate/migrate · error
unable to parse file %v
Error message
unable to parse file %v
What it means
Raised in Github.readDirectory when source.DefaultParse succeeds on a filename but g.migrations.Append rejects it — almost always a duplicate migration version (same version number already appended). The message includes the offending filename.
Source
Thrown at source/github/github.go:130
g.config.Repo,
g.config.Path,
g.options,
)
if err != nil {
return err
}
if fileContent != nil {
return ErrNoDir
}
for _, fi := range dirContents {
m, err := source.DefaultParse(*fi.Name)
if err != nil {
continue // ignore files that we can't parse
}
if !g.migrations.Append(m) {
return fmt.Errorf("unable to parse file %v", *fi.Name)
}
}
return nil
}
func (g *Github) ensureFields() {
if g.config == nil {
g.config = &Config{}
}
}
func (g *Github) Close() error {
return nil
}
func (g *Github) First() (version uint, err error) {
g.ensureFields()View on GitHub (pinned to 01a9643f14)
Solutions
- Rename the duplicate file so it has a unique version number (e.g. 0002_...)
- Check the target directory on the configured ref for two files sharing a version prefix
- Ensure only one migrations directory is being read (avoid overlapping Path entries)
Example fix
// before 0001_create_users.up.sql 0001_create_users.up.sql // duplicate version 1 // after 0001_create_users.up.sql 0002_create_users.up.sql // unique version
Defensive patterns
Strategy: validation
Validate before calling
// pre-flight: detect duplicate versions locally before pushing migrations
seen := map[uint]struct{}{}
for _, name := range filenames {
m, err := source.DefaultParse(name)
if err != nil {
continue
}
if _, dup := seen[m.Version]; dup {
return fmt.Errorf("duplicate migration version %d in %s", m.Version, name)
}
seen[m.Version] = struct{}{}
} Try / catch
d, err := source.Open(srcURL)
if err != nil {
if strings.Contains(err.Error(), "unable to parse file") {
return fmt.Errorf("duplicate migration version in repo directory: %w", err)
}
return err
} Prevention
- Enforce unique version prefixes in CI before merging migration PRs
- Never copy old migration files into a directory that already has that version
- Use a naming convention like NNNN_description.up.sql with monotonic numbers
When it happens
Trigger: Two files in the GitHub directory resolve to the same version, e.g. '0001_init.up.sql' and '0001_init.up.sql' across folders folded into one path, or '1_fix.sql' and '0001_fix.sql' both parsing to version 1.
Common situations: Reused version numbers after copying migration files between branches/environments; case-sensitivity or formatting differences creating near-duplicates; files with same numeric prefix but different direction/name.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- database is dirty
- x-migrations-table must be quoted (for instance '"migrate"."
- unable to parse option x-multi-statement: %w
- "%s" MigrationsTable contains too many dot characters
- x-migrations-table must be quoted (for instance '"migrate"."
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/419573ec9cd7dd9c.
Report an issue: GitHub.