{"record":{"id":"a13ffdbe1f2cd811","repo":"mattermost-community/focalboard","slug":"cannot-get-migration-state-w","errorCode":null,"errorMessage":"cannot get migration state: %w","messagePattern":"cannot get migration state: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/services/store/sqlstore/data_migrations.go","lineNumber":75,"sourceCode":"\n\trows, err := s.getQueryBuilder(db).\n\t\tSelect(blocksFields...).\n\t\tFrom(s.tablePrefix + \"blocks\").\n\t\tWhere(fmt.Sprintf(\"id IN (%s)\", subquery)).\n\t\tQuery()\n\tif err != nil {\n\t\ts.logger.Error(`getBlocksWithSameID ERROR`, mlog.Err(err))\n\t\treturn nil, err\n\t}\n\tdefer s.CloseRows(rows)\n\n\treturn s.blocksFromRows(rows)\n}\n\nfunc (s *SQLStore) RunUniqueIDsMigration() error {\n\tsetting, err := s.GetSystemSetting(UniqueIDsMigrationKey)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot get migration state: %w\", err)\n\t}\n\n\t// If the migration is already completed, do not run it again.\n\tif hasAlreadyRun, _ := strconv.ParseBool(setting); hasAlreadyRun {\n\t\treturn nil\n\t}\n\n\ts.logger.Debug(\"Running Unique IDs migration\")\n\n\ttx, txErr := s.db.BeginTx(context.Background(), nil)\n\tif txErr != nil {\n\t\treturn txErr\n\t}\n\n\tblocks, err := s.getBlocksWithSameID(tx)\n\tif err != nil {\n\t\tif rollbackErr := tx.Rollback(); rollbackErr != nil {\n\t\t\ts.logger.Error(\"Unique IDs transaction rollback error\", mlog.Err(rollbackErr), mlog.String(\"methodName\", \"getBlocksWithSameID\"))","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/services/store/sqlstore/data_migrations.go#L57-L93","documentation":"Wraparound error in SQLStore.RunUniqueIDsMigration (server/services/store/sqlstore/data_migrations.go:75). Before running the unique-IDs data migration, the store reads the UniqueIDsMigrationKey system setting to check whether the migration already completed. If GetSystemSetting itself returns an error (not merely an empty value), this error is wrapped so the caller (runMigrationSequence) knows migration state lookup failed.","triggerScenarios":"Calling RunUniqueIDsMigration when the system settings read fails: database connection error, corrupt/locked SystemSettings table, query timeout, or missing table due to incomplete schema initialization.","commonSituations":"Fresh installs where schema init failed; DB user lacking SELECT permission on the SystemSettings table; transient DB outage during server startup when runMigrationSequence executes; proxy/pool timeouts on large settings rows.","solutions":["Check the wrapped %w cause for the exact DB error (connection, permissions, missing table).","Verify the SystemSettings table exists and the DB user has SELECT rights.","Check DB connectivity and retry server start; the migration runs only once so a healthy retry is safe.","Fix schema initialization failures before the app starts migrations.","If the setting value is empty/absent, note the store tolerates it (ParseBool error is ignored) — only read failures produce this error."],"exampleFix":"// before\nerr := store.RunUniqueIDsMigration()\nif err != nil {\n\tlog.Fatal(err)\n}\n// after\nerr := store.RunUniqueIDsMigration()\nif err != nil {\n\tif isTransientDBError(errors.Unwrap(err)) {\n\t\tlog.Println(\"transient DB error, retrying migration\", err)\n\t\ttime.Sleep(time.Second)\n\t\terr = store.RunUniqueIDsMigration()\n\t}\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}","handlingStrategy":"retry","validationCode":"if err := db.Ping(); err != nil { return fmt.Errorf(\"db unavailable, defer migrations: %w\", err) }","typeGuard":"func isMigrationStateError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"cannot get migration state\")\n}","tryCatchPattern":"err := store.RunUniqueIDsMigration()\nif err != nil {\n\tif isMigrationStateError(err) && isTransient(errors.Unwrap(err)) {\n\t\ttime.Sleep(backoff)\n\t\terr = store.RunUniqueIDsMigration()\n\t}\n\tif err != nil { log.Fatal(err) }\n}","preventionTips":["Verify schema initialization completed before running migrations","Ensure the app DB user can SELECT from SystemSettings","Start only one instance against a DB at a time for migrations","Retry on transient DB errors; the migration flag prevents double-run"],"tags":["database","migration","startup","focalboard"],"backgroundTag":"migration-state-check-failed","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}