gastownhall/beads · error
no version prefix
Error message
no version prefix
What it means
parseVersion extracts the numeric version prefix from a migration filename of the form `<version>_<name>.sql`. This error means the filename has no `_<description>` suffix to split on, so no version prefix can be parsed — the migration file is misnamed.
Source
Thrown at internal/storage/schema/schema.go:547
}
return string(data), nil
}
// IgnoredMigrationSQL is MigrationSQL's ignored-lane counterpart: the frozen
// bytes of an ignored-source migration file (e.g. "0019_create_events.up.sql"),
// for engine-based frozen-guard tests of clone-local DDL.
func IgnoredMigrationSQL(name string) (string, error) {
data, err := ignoredSource.files.ReadFile(ignoredSource.dir + "/" + name)
if err != nil {
return "", err
}
return string(data), nil
}
func parseVersion(name string) (int, error) {
parts := strings.SplitN(name, "_", 2)
if len(parts) == 0 {
return 0, fmt.Errorf("no version prefix")
}
return strconv.Atoi(parts[0])
}
// MigrateUpTo applies main-source migrations up to and including maxVersion,
// without the dirty-table guards, backfills, rekeys, or ignored-source pass
// that MigrateUp layers on. It exists so cross-upgrade-boundary tests
// (bd-6dnrw.16) can reconstruct the schema as it stood at a historical
// release and use it as a Dolt merge ancestor. Production code must use
// MigrateUp: stopping short of the latest version on a real database leaves
// it half-upgraded by design.
func MigrateUpTo(ctx context.Context, db DBConn, maxVersion int) (int, error) {
applied, _, err := mainSource.migrate(ctx, db, maxVersion)
return applied, err
}
func MigrateUp(ctx context.Context, db DBConn) (int, error) {
// Re-assert the canonical dolt_ignore patterns before anything else, andView on GitHub (pinned to 71377f2769)
Solutions
- Rename the migration file to `<version>_<slug>.sql`, e.g. `0007_add_index.sql`
- Ensure version numbers are monotonically increasing integers
- Remove any stray non-migration files from the migrations directory
- Rebuild and re-run migrations to confirm the file list parses
Example fix
// before internal/storage/schema/migrations/migrate.sql // after internal/storage/schema/migrations/0007_migrate.sql
Defensive patterns
Strategy: validation
Validate before calling
// lint migration filenames in CI
bad, _ := filepath.Glob("internal/storage/schema/migrations/*.sql")
for _, f := range bad {
base := filepath.Base(f)
if !regexp.MustCompile(`^\d+_.+\.sql$`).MatchString(base) {
panic("bad migration filename: " + base)
}
} Prevention
- Follow the `<version>_<slug>.sql` naming convention for every new migration
- Add a CI check that validates migration filenames before merge
- Never hand-rename migration files without preserving the numeric prefix and underscore
When it happens
Trigger: The `list` function scanning the migrations directory encounters an embedded migration filename that doesn't match the `<N>_<slug>` convention (e.g. `migrate.sql` or `1.sql` with no underscore), so strings.SplitN(name, "_", 2) yields no split.
Common situations: A developer added a new migration file with a non-conforming name; a file was renamed during a merge losing its `_description` suffix; a stray non-migration file landed in the migrations directory.
Related errors
- clone from %s succeeded, but the database needs %d schema %s
- failed to open JSONL: %w
- failed to read JSONL: %w
- building hook migration plan: %w
- hook migration is blocked: - %s
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ba0e51573b52cff4.
Report an issue: GitHub.