{"record":{"id":"07be3f96bf6d89ff","repo":"mattermost-community/focalboard","slug":"cannot-commit-category-uuids-transaction-w","errorCode":null,"errorMessage":"cannot commit category UUIDs transaction: %w","messagePattern":"cannot commit category UUIDs transaction: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/services/store/sqlstore/data_migrations.go","lineNumber":165,"sourceCode":"\t\treturn nil\n\t}\n\n\ts.logger.Debug(\"Running category UUID ID migration\")\n\n\ttx, txErr := s.db.BeginTx(context.Background(), nil)\n\tif txErr != nil {\n\t\treturn txErr\n\t}\n\n\tif err := s.setSystemSetting(tx, CategoryUUIDIDMigrationKey, strconv.FormatBool(true)); err != nil {\n\t\tif rollbackErr := tx.Rollback(); rollbackErr != nil {\n\t\t\ts.logger.Error(\"category UUIDs transaction rollback error\", mlog.Err(rollbackErr), mlog.String(\"methodName\", \"setSystemSetting\"))\n\t\t}\n\t\treturn fmt.Errorf(\"cannot mark migration as completed: %w\", err)\n\t}\n\n\tif err := tx.Commit(); err != nil {\n\t\treturn fmt.Errorf(\"cannot commit category UUIDs transaction: %w\", err)\n\t}\n\n\ts.logger.Debug(\"category UUIDs migration finished successfully\")\n\treturn nil\n}\n\nfunc (s *SQLStore) RunFixCollationsAndCharsetsMigration() error {\n\t// This is for MySQL only\n\tif s.dbType != model.MysqlDBType {\n\t\treturn nil\n\t}\n\n\t// get collation and charSet setting that Channels is using.\n\t// when personal server or unit testing, no channels tables exist so just set to a default.\n\tvar collation string\n\tvar charSet string\n\tvar err error\n\tif os.Getenv(\"FOCALBOARD_UNIT_TESTING\") == \"1\" {","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/services/store/sqlstore/data_migrations.go#L147-L183","documentation":"Error from SQLStore.RunCategoryUUIDIDMigration (server/services/store/sqlstore/data_migrations.go:165). The final step of the migration is tx.Commit(); if the commit fails, the DB discards all in-transaction ID rewrites and the error is wrapped as 'cannot commit category UUIDs transaction'.","triggerScenarios":"Calling RunCategoryUUIDIDMigration when tx.Commit() fails: connection loss during the long-running rewrite transaction, serialization failure or deadlock detected at commit, or DB failover/restart mid-migration.","commonSituations":"Instances with many boards/categories making the migration transaction long-lived; flaky networks or aggressive load-balancer idle timeouts; managed-DB failovers during app startup; concurrent administrative DDL locking the tables at commit time.","solutions":["Check the wrapped cause; connection-loss and serialization errors are safe to retry because the commit is atomic and the flag was never written.","Restore stable connectivity / wait out failover, then restart the app or re-trigger migrations.","Run the migration in a maintenance window to keep the transaction short and avoid contention.","Increase LB/proxy idle timeouts for migration connections.","Confirm success on retry via the 'category UUIDs migration finished successfully' debug log and the CategoryUUIDIDMigrationKey setting being true."],"exampleFix":"// before\nif err := store.RunCategoryUUIDIDMigration(); err != nil {\n\treturn fmt.Errorf(\"migration failed: %v\", err)\n}\n// after\nif err := store.RunCategoryUUIDIDMigration(); err != nil {\n\t// transaction rolled back atomically; safe to retry once connectivity is restored\n\treturn fmt.Errorf(\"category migration aborted at commit (retryable): %w\", err)\n}","handlingStrategy":"retry","validationCode":"if err := db.PingContext(ctx); err != nil { return err } // ensure DB is stable before a long rewrite transaction","typeGuard":"func isCategoryCommitFailedError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"cannot commit category UUIDs transaction\")\n}","tryCatchPattern":"err := store.RunCategoryUUIDIDMigration()\nif err != nil {\n\tif isCategoryCommitFailedError(err) {\n\t\t// atomic rollback; wait for DB stability and retry\n\t\ttime.Sleep(30 * time.Second)\n\t\terr = store.RunCategoryUUIDIDMigration()\n\t}\n\tif err != nil { return err }\n}","preventionTips":["Run category migrations in a maintenance window","Verify DB failover health after any commit failure before retrying","Increase proxy idle timeouts for long-running transactions","Confirm success via the debug log and the CategoryUUIDIDMigrationKey flag"],"tags":["database","migration","transaction-commit","focalboard"],"backgroundTag":"transaction-commit-failed","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}