{"record":{"id":"eaba4d366b800635","repo":"MHSanaei/3x-ui","slug":"database-is-not-initialized","errorCode":null,"errorMessage":"database is not initialized","messagePattern":"database is not initialized","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/database/db.go","lineNumber":2185,"sourceCode":"\treturn errors.Is(err, gorm.ErrRecordNotFound)\n}\n\nfunc IsSQLiteDB(file io.ReaderAt) (bool, error) {\n\tsignature := []byte(\"SQLite format 3\\x00\")\n\tbuf := make([]byte, len(signature))\n\t_, err := file.ReadAt(buf, 0)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\treturn bytes.Equal(buf, signature), nil\n}\n\nfunc BackupSQLite(dstPath string) (err error) {\n\tif IsPostgres() {\n\t\treturn errors.New(\"sqlite backup is unavailable for PostgreSQL\")\n\t}\n\tif db == nil {\n\t\treturn errors.New(\"database is not initialized\")\n\t}\n\tif _, err := os.Lstat(dstPath); err == nil {\n\t\treturn fmt.Errorf(\"sqlite backup destination already exists: %s\", dstPath)\n\t} else if !errors.Is(err, os.ErrNotExist) {\n\t\treturn err\n\t}\n\tdefer func() {\n\t\tif err != nil {\n\t\t\t_ = os.Remove(dstPath)\n\t\t}\n\t}()\n\n\tctx, cancel := context.WithTimeout(context.Background(), backupSQLiteTimeout)\n\tdefer cancel()\n\n\tsourceDB, err := db.DB()\n\tif err != nil {\n\t\treturn err","sourceCodeStart":2167,"sourceCodeEnd":2203,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/database/db.go#L2167-L2203","documentation":"BackupSQLite returns 'database is not initialized' when the package-level db handle is nil — i.e. BackupSQLite was called before database.InitDB succeeded (or after CloseDB). The function assumes the singleton GORM connection is live; without it there is no source database to copy from. This is an ordering bug in the caller, not a data problem.","triggerScenarios":"Calling BackupSQLite from a CLI subcommand path that skips InitDB; invoking it in a unit test without database.InitDB(t.TempDir()...); calling after CloseDB during shutdown.","commonSituations":"Custom tooling or tests that link the database package and call backup directly; startup races where a job fires before InitDB completes.","solutions":["Call database.InitDB(...) (the app's normal boot sequence) before BackupSQLite","In tests, follow the repo pattern: database.InitDB(filepath.Join(t.TempDir(), \"x-ui.db\")) with t.Cleanup(database.CloseDB)","If this appears at runtime, check logs for an earlier InitDB failure that was swallowed"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if database.GetDB() == nil { // or expose an IsInitialized check\n    return errors.New(\"init database before backup\")\n}","typeGuard":null,"tryCatchPattern":"if err := database.BackupSQLite(dst); err != nil {\n    if strings.Contains(err.Error(), \"not initialized\") {\n        log.Fatal(\"InitDB must run before BackupSQLite — check boot order\")\n    }\n    return err\n}","preventionTips":["Always boot through the standard InitDB sequence before backup calls","In tests use database.InitDB(filepath.Join(t.TempDir(), \"x-ui.db\")) with t.Cleanup(database.CloseDB)"],"tags":["database","initialization","backup","sqlite"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}