{"record":{"id":"3e17b6432b1f57a4","repo":"semaphoreui/semaphore","slug":"invalid-migration-version-minor-part-s","errorCode":null,"errorMessage":"invalid migration version minor part %s","messagePattern":"invalid migration version minor part (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db/Migration.go","lineNumber":174,"sourceCode":"\nfunc (m Migration) ParseVersion() (res MigrationVersion, err error) {\n\n\tparts := strings.Split(m.Version, \".\")\n\n\tif len(parts) < 2 {\n\t\terr = fmt.Errorf(\"invalid migration version format %s\", m.Version)\n\t\treturn\n\t}\n\n\tres.Major, err = strconv.Atoi(parts[0])\n\tif err != nil {\n\t\terr = fmt.Errorf(\"invalid migration version major part %s\", parts[0])\n\t\treturn\n\t}\n\n\tres.Minor, err = strconv.Atoi(parts[1])\n\tif err != nil {\n\t\terr = fmt.Errorf(\"invalid migration version minor part %s\", parts[1])\n\t\treturn\n\t}\n\n\tif len(parts) < 3 {\n\t\tres.Patch = math.MaxInt\n\t\treturn\n\t}\n\n\tres.Patch, err = strconv.Atoi(parts[2])\n\tif err != nil {\n\t\terr = fmt.Errorf(\"invalid migration version patch part %s\", parts[2])\n\t\treturn\n\t}\n\n\treturn\n}\n\nfunc (v MigrationVersion) Compare(o MigrationVersion) int {","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/db/Migration.go#L156-L192","documentation":"ParseVersion converts the second dot-separated segment of a migration version string to an integer for the Minor field. If strconv.Atoi fails on parts[1], it returns 'invalid migration version minor part %s'. This only happens when a second segment exists but is non-numeric.","triggerScenarios":"Calling Compare/ParseVersion with a version like '1.x' or '1.beta' — the major part parses but the minor segment is not an integer.","commonSituations":"Typos in migration version strings ('1..0', '1.o'); using branch names or labels as minor versions; copying version strings from tags like '1.rc1'.","solutions":["Correct the migration version so the second segment is an integer, e.g. '1.2' instead of '1.x'","Use the two-part format 'major.minor' or three-part 'major.minor.patch' with all numeric parts","Validate version strings with a regex like ^\\d+(\\.\\d+)?(\\.\\d+)?$ before invoking ParseVersion/Compare"],"exampleFix":"// before\nm.Version = \"2.beta\"\n// after\nm.Version = \"2.0\"","handlingStrategy":"validation","validationCode":"parts := strings.Split(version, \".\")\nif len(parts) < 2 {\n    return fmt.Errorf(\"version %q needs a numeric minor part\", version)\n}\nif _, err := strconv.Atoi(parts[1]); err != nil {\n    return fmt.Errorf(\"minor part %q is not numeric\", parts[1])\n}","typeGuard":null,"tryCatchPattern":"if err := Compare(a, b); err != nil {\n    var se *strconv.NumError\n    if errors.As(err, &se) || strings.Contains(err.Error(), \"minor part\") {\n        return fmt.Errorf(\"fix version string: %w\", err)\n    }\n    return err\n}","preventionTips":["Keep minor segments strictly numeric","Avoid labels like 'beta' or 'rc1' inside the version string","Trim whitespace and stray dots before parsing"],"tags":["database","migration","parsing"],"backgroundTag":"invalid-argument-format","analyzedSha":"1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa","analyzedAt":"2026-09-07T11:00:33.293Z","contentChangedAt":"2026-09-07T11:00:33.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}