{"record":{"id":"eb4b501f96957695","repo":"golang-migrate/migrate","slug":"unable-to-parse-file-v-eb4b50","errorCode":null,"errorMessage":"unable to parse file %v","messagePattern":"unable to parse file (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"source/gitlab/gitlab.go","lineNumber":143,"sourceCode":"\t\tif response.StatusCode != http.StatusOK {\n\t\t\treturn ErrInvalidResponse\n\t\t}\n\n\t\tnodes = append(nodes, n...)\n\t\tif response.CurrentPage >= response.TotalPages {\n\t\t\tbreak\n\t\t}\n\t\tg.listOptions.Page = response.NextPage\n\t}\n\n\tfor i := range nodes {\n\t\tm, err := g.nodeToMigration(nodes[i])\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tif !g.migrations.Append(m) {\n\t\t\treturn fmt.Errorf(\"unable to parse file %v\", nodes[i].Name)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (g *Gitlab) nodeToMigration(node *gitlab.TreeNode) (*source.Migration, error) {\n\tm := source.Regex.FindStringSubmatch(node.Name)\n\tif len(m) == 5 {\n\t\tversionUint64, err := strconv.ParseUint(m[1], 10, 64)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &source.Migration{\n\t\t\tVersion:    uint(versionUint64),\n\t\t\tIdentifier: m[2],\n\t\t\tDirection:  source.Direction(m[3]),\n\t\t\tRaw:        g.path + \"/\" + node.Name,","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/source/gitlab/gitlab.go#L125-L161","documentation":"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.","triggerScenarios":"Listing migration files in the repository where two files resolve to the same version number, so the second Append(m) returns false.","commonSituations":"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.","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"],"exampleFix":"// before (repo files)\n002_create_users.sql\n002_create_posts.sql\n// after\n002_create_users.sql\n003_create_posts.sql","handlingStrategy":"validation","validationCode":"seen := map[uint]bool{}\nfor _, name := range fileNames {\n    m, err := source.DefaultParse(name)\n    if err != nil {\n        continue\n    }\n    if seen[m.Version] {\n        return fmt.Errorf(\"duplicate migration version %d (%s)\", m.Version, name)\n    }\n    seen[m.Version] = true\n}","typeGuard":null,"tryCatchPattern":"if err := readDirectory(); err != nil {\n    if strings.HasPrefix(err.Error(), \"unable to parse file\") {\n        return fmt.Errorf(\"duplicate migration versions in repo: %w\", err)\n    }\n    return err\n}","preventionTips":["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"],"tags":["gitlab","migration","duplicate","naming"],"backgroundTag":"duplicate-migration-version","analyzedSha":"01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a","analyzedAt":"2026-09-02T19:38:29.671Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}