{"record":{"id":"8b40380cef4d1118","repo":"MHSanaei/3x-ui","slug":"upgrade-panel-schema-for-t-w","errorCode":null,"errorMessage":"upgrade panel schema for %T: %w","messagePattern":"upgrade panel schema for %T: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/database/migrate_data.go","lineNumber":341,"sourceCode":"func PrepareSQLiteForMigration(dbPath string) error {\n\tgdb, err := gorm.Open(sqlite.Open(dbPath+\"?_busy_timeout=10000\"), &gorm.Config{Logger: logger.Discard})\n\tif err != nil {\n\t\treturn err\n\t}\n\tsqlDB, err := gdb.DB()\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer sqlDB.Close()\n\n\tfor _, table := range []string{\"users\", \"settings\", \"inbounds\"} {\n\t\tif !sqliteTableExists(sqlDB, table) {\n\t\t\treturn fmt.Errorf(\"not a 3x-ui panel database: required table %q is missing\", table)\n\t\t}\n\t}\n\tfor _, m := range migrationModels() {\n\t\tif err := gdb.AutoMigrate(m); err != nil && !isIgnorableDuplicateColumnErr(gdb, err, m) {\n\t\t\treturn fmt.Errorf(\"upgrade panel schema for %T: %w\", m, err)\n\t\t}\n\t}\n\treturn nil\n}\n","sourceCodeStart":323,"sourceCodeEnd":346,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/database/migrate_data.go#L323-L346","documentation":"Thrown by PrepareSQLiteForMigration when AutoMigrate(m) fails while upgrading the old SQLite backup to the current panel schema (so the row copy can read newer tables/columns), and the error is not an ignorable duplicate-column condition. This runs on the SQLite source copy before migration starts; a failure aborts safely with nothing written to Postgres.","triggerScenarios":"A backup from a panel version whose column types conflict with current models (e.g. an id or timestamp column stored with an incompatible type/affinity); a schema hand-edited at runtime; the file locked by another process; a duplicate-column error not matching isIgnorableDuplicateColumnErr's accepted shapes.","commonSituations":"Migrating backups skipped across many major versions (very old panel → current); DBs previously touched by forks or manual ALTERs; running the preparation while the file is open in a SQLite browser.","solutions":["Note the model %T in the message, open the backup with sqlite3, and compare that table's PRAGMA table_info against the model's expected columns/types.","If the backup is several versions behind, first restore it into a temporary panel of an intermediate version, let it upgrade, back it up again, then migrate.","Close other processes holding the file and retry.","Keep an untouched copy of the backup — AutoMigrate mutates the source file, so always prepare a copy, never the only original."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// snapshot the backup before PrepareSQLiteForMigration mutates it\ncpSrc := dbPath + \".work\"\nif err := copyFile(dbPath, cpSrc); err != nil { return err }\nif err := PrepareSQLiteForMigration(cpSrc); err != nil { /* original untouched */ }","typeGuard":null,"tryCatchPattern":"err := PrepareSQLiteForMigration(cpPath)\nif err != nil && strings.Contains(err.Error(), \"upgrade panel schema\") {\n    // restore into an intermediate panel version first, re-backup, then retry with a fresh copy\n}","preventionTips":["Operate on a copy — AutoMigrate modifies the source file in place.","Step very old backups through intermediate panel versions.","Keep no other process (SQLite browser) open on the file."],"tags":["database","sqlite","automigrate","migration","schema-upgrade"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}