{"record":{"id":"ba0e51573b52cff4","repo":"gastownhall/beads","slug":"no-version-prefix","errorCode":null,"errorMessage":"no version prefix","messagePattern":"no version prefix","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/schema.go","lineNumber":547,"sourceCode":"\t}\n\treturn string(data), nil\n}\n\n// IgnoredMigrationSQL is MigrationSQL's ignored-lane counterpart: the frozen\n// bytes of an ignored-source migration file (e.g. \"0019_create_events.up.sql\"),\n// for engine-based frozen-guard tests of clone-local DDL.\nfunc IgnoredMigrationSQL(name string) (string, error) {\n\tdata, err := ignoredSource.files.ReadFile(ignoredSource.dir + \"/\" + name)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn string(data), nil\n}\n\nfunc parseVersion(name string) (int, error) {\n\tparts := strings.SplitN(name, \"_\", 2)\n\tif len(parts) == 0 {\n\t\treturn 0, fmt.Errorf(\"no version prefix\")\n\t}\n\treturn strconv.Atoi(parts[0])\n}\n\n// MigrateUpTo applies main-source migrations up to and including maxVersion,\n// without the dirty-table guards, backfills, rekeys, or ignored-source pass\n// that MigrateUp layers on. It exists so cross-upgrade-boundary tests\n// (bd-6dnrw.16) can reconstruct the schema as it stood at a historical\n// release and use it as a Dolt merge ancestor. Production code must use\n// MigrateUp: stopping short of the latest version on a real database leaves\n// it half-upgraded by design.\nfunc MigrateUpTo(ctx context.Context, db DBConn, maxVersion int) (int, error) {\n\tapplied, _, err := mainSource.migrate(ctx, db, maxVersion)\n\treturn applied, err\n}\n\nfunc MigrateUp(ctx context.Context, db DBConn) (int, error) {\n\t// Re-assert the canonical dolt_ignore patterns before anything else, and","sourceCodeStart":529,"sourceCodeEnd":565,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/schema.go#L529-L565","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ninternal/storage/schema/migrations/migrate.sql\n// after\ninternal/storage/schema/migrations/0007_migrate.sql","handlingStrategy":"validation","validationCode":"// lint migration filenames in CI\nbad, _ := filepath.Glob(\"internal/storage/schema/migrations/*.sql\")\nfor _, f := range bad {\n\tbase := filepath.Base(f)\n\tif !regexp.MustCompile(`^\\d+_.+\\.sql$`).MatchString(base) {\n\t\tpanic(\"bad migration filename: \" + base)\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["migration","naming","embedded-files"],"backgroundTag":"migration-filename-invalid","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}