golang-migrate/migrate · error
unable to parse file %v
Error message
unable to parse file %v
What it means
This error is raised by the gitlab driver's readDirectory when a migration entry returned by the GitLab API matches a migration filename pattern but Append fails — i.e., a migration with the same version number was already appended. Note that files that fail source.DefaultParse are silently skipped (continue); this error only fires for duplicate version numbers among parseable files.
Source
Thrown at source/gitlab/gitlab.go:143
if response.StatusCode != http.StatusOK {
return ErrInvalidResponse
}
nodes = append(nodes, n...)
if response.CurrentPage >= response.TotalPages {
break
}
g.listOptions.Page = response.NextPage
}
for i := range nodes {
m, err := g.nodeToMigration(nodes[i])
if err != nil {
continue
}
if !g.migrations.Append(m) {
return fmt.Errorf("unable to parse file %v", nodes[i].Name)
}
}
return nil
}
func (g *Gitlab) nodeToMigration(node *gitlab.TreeNode) (*source.Migration, error) {
m := source.Regex.FindStringSubmatch(node.Name)
if len(m) == 5 {
versionUint64, err := strconv.ParseUint(m[1], 10, 64)
if err != nil {
return nil, err
}
return &source.Migration{
Version: uint(versionUint64),
Identifier: m[2],
Direction: source.Direction(m[3]),
Raw: g.path + "/" + node.Name,View on GitHub (pinned to 01a9643f14)
Solutions
- List files in the migrations directory and find duplicate version numbers among parseable files
- Rename one of the duplicate files to a unique version number
- Remember .down.sql files are handled via direction, so duplicates across up/down naming are only a problem if versions collide after parsing
- Re-run migrations after fixing the file names
Example fix
// before (repo files) 002_create_users.sql 002_create_posts.sql // after 002_create_users.sql 003_create_posts.sql
Defensive patterns
Strategy: validation
Validate before calling
seen := map[uint]bool{}
for _, name := range fileNames {
m, err := source.DefaultParse(name)
if err != nil {
continue
}
if seen[m.Version] {
return fmt.Errorf("duplicate migration version %d (%s)", m.Version, name)
}
seen[m.Version] = true
} Try / catch
if err := readDirectory(); err != nil {
if strings.HasPrefix(err.Error(), "unable to parse file") {
return fmt.Errorf("duplicate migration versions in repo: %w", err)
}
return err
} Prevention
- Enforce unique version numbers in CI before merging migration PRs
- Use timestamps instead of small integers for versions to reduce collisions
- Avoid committing backups or copies of migration files
- Keep one migration per version number; down migrations share the version by design
When it happens
Trigger: Listing migration files in the repository where two files resolve to the same version number, so the second Append(m) returns false.
Common situations: Duplicated migration version numbers in the repo (e.g. 001_init.sql and 001_init.down.sql counted correctly, but two files like 002_a.sql and 002_b.sql share version 2), bad branch merges that duplicated numbered files.
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
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/eb4b501f96957695.
Report an issue: GitHub.