{"record":{"id":"88f873374141474d","repo":"MHSanaei/3x-ui","slug":"source-sqlite-not-found-at-s-w-88f873","errorCode":null,"errorMessage":"source sqlite not found at %s: %w","messagePattern":"source sqlite not found at (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/database/migrate_data.go","lineNumber":69,"sourceCode":"\t\t&model.ClientExternalLink{},\n\t\t&model.ClientGroup{},\n\t\t&model.InboundFallback{},\n\t\t&model.Host{},\n\t\t&model.NodeClientTraffic{},\n\t\t&model.NodeClientIp{},\n\t\t&model.ClientGlobalTraffic{},\n\t\t&model.OutboundSubscription{},\n\t}\n}\n\n// MigrateData copies every row from the configured SQLite file at srcPath into\n// a fresh PostgreSQL database described by dstDSN. The destination tables are\n// (re)created with AutoMigrate; truncate and copy then run in one transaction,\n// so a failed migration leaves the destination data unchanged. Source data is\n// left untouched.\nfunc MigrateData(srcPath, dstDSN string) error {\n\tif _, err := os.Stat(srcPath); err != nil {\n\t\treturn fmt.Errorf(\"source sqlite not found at %s: %w\", srcPath, err)\n\t}\n\tif dstDSN == \"\" {\n\t\treturn errors.New(\"destination DSN is required\")\n\t}\n\n\tif err := os.MkdirAll(path.Dir(srcPath), 0o755); err != nil {\n\t\treturn err\n\t}\n\n\tsrcDSN := srcPath + \"?_journal_mode=WAL&_busy_timeout=10000\"\n\tsrc, err := gorm.Open(sqlite.Open(srcDSN), &gorm.Config{Logger: logger.Discard})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"open sqlite source: %w\", err)\n\t}\n\tsrcSQL, err := src.DB()\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/database/migrate_data.go#L51-L87","documentation":"MigrateData (SQLite → PostgreSQL) stats srcPath up front and wraps the failure: the configured SQLite source file does not exist. This is the same guard DumpSQLiteToBytes uses, applied to the migration entrypoint, so the copy never starts with a missing source. Typically a wrong path in the migrate-db invocation.","triggerScenarios":"Running `x-ui migrate-db` (or MigrateData) with srcPath pointing somewhere other than the real x-ui.db; running on a host where the panel stores its DB elsewhere (different install prefix, Windows layout); path typo.","commonSituations":"Migration prep on a fresh box before copying the old DB over; Docker volume mounted at a different path than assumed; container exec with wrong workdir-relative path.","solutions":["Locate the real DB (default /etc/x-ui/x-ui.db; check the panel's data dir) and pass its absolute path.","If migrating from another server, copy the x-ui.db over first, then run migrate.","Confirm the path is visible inside the container/mount namespace when running in Docker."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if _, err := os.Stat(srcPath); err != nil {\n    return fmt.Errorf(\"copy the panel DB first (default /etc/x-ui/x-ui.db): %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run `x-ui migrate-db` on the host/container that actually holds x-ui.db, with the absolute path.","Copy the old server's DB over before starting a SQLite→Postgres migration."],"tags":["database","sqlite","postgres","migration"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}