golang-migrate/migrate · error

unable to parse file %v

Error message

unable to parse file %v

What it means

readDirectory parses each file returned by the Bitbucket ListFiles API with source.DefaultParse. Unparseable names are skipped, but if a name parses and migrations.Append still returns false — which only happens when another migration with the same version was already appended — the driver aborts with 'unable to parse file %v'. Despite the wording, the actual cause is a duplicate migration version, not a parse failure.

Source

Thrown at source/bitbucket/bitbucket.go:116

		RepoSlug: b.config.Repo,
		Ref:      b.config.Ref,
		Path:     b.config.Path,
	}

	dirContents, err := b.client.Repositories.Repository.ListFiles(fOpt)

	if err != nil {
		return err
	}

	for _, fi := range dirContents {

		m, err := source.DefaultParse(filepath.Base(fi.Path))
		if err != nil {
			continue // ignore files that we can't parse
		}
		if !b.migrations.Append(m) {
			return fmt.Errorf("unable to parse file %v", fi.Path)
		}
	}

	return nil
}

func (b *Bitbucket) ensureFields() {
	if b.config == nil {
		b.config = &Config{}
	}
}

func (b *Bitbucket) Close() error {
	return nil
}

func (b *Bitbucket) First() (version uint, er error) {
	b.ensureFields()

View on GitHub (pinned to 01a9643f14)

Solutions

  1. Find the duplicate version: list repo files and compute version prefixes; rename or delete one of the colliding migrations.
  2. Standardize on zero-padded seq prefixes (e.g. 000001_) so `1_` and `001_` no longer collide after parsing.
  3. Use `migrate create` for every new migration so versions are generated uniquely instead of hand-written.
  4. Fix the branch history (rebase/dedupe) if the same migration was merged twice, then retry.

Example fix

// before
migrations/1_add_users.up.sql
migrations/001_add_users_v2.up.sql  // same parsed version 1
// after
migrations/000001_add_users.up.sql
migrations/000002_add_users_v2.up.sql
Defensive patterns

Strategy: validation

Validate before calling

// fetch file list and check for duplicate versions before WithInstance
seen := map[uint64]string{}
for _, fi := range dirContents {
    m, err := source.DefaultParse(filepath.Base(fi.Path))
    if err != nil {
        continue
    }
    if prev, dup := seen[m.Version]; dup {
        return fmt.Errorf("duplicate version %d: %s and %s", m.Version, prev, fi.Path)
    }
    seen[m.Version] = fi.Path
}

Try / catch

d, err := bitbucket.WithInstance(cl, cfg)
if err != nil && strings.HasPrefix(err.Error(), "unable to parse file") {
    f := strings.TrimPrefix(err.Error(), "unable to parse file ")
    return fmt.Errorf("duplicate migration version detected for %s; dedupe and retry", f)
}

Prevention

When it happens

Trigger: bitbucket.WithInstance/Open where the repo listing contains two files whose basenames yield the same version, e.g. `1_foo.up.sql` and `001_bar.up.sql`, or the same filename present via path casing differences.

Common situations: Zero-padding inconsistencies between team members' created migrations; a migration cherry-picked or merged twice from branches; renamed file keeping an old version prefix.

Understand the failure class

Related errors


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