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

  1. List files in the migrations directory and find duplicate version numbers among parseable files
  2. Rename one of the duplicate files to a unique version number
  3. Remember .down.sql files are handled via direction, so duplicates across up/down naming are only a problem if versions collide after parsing
  4. 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

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

Related errors


AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02). Data as JSON: /api/errors/eb4b501f96957695. Report an issue: GitHub.