MHSanaei/3x-ui · error
database is not initialized
Error message
database is not initialized
What it means
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.
Source
Thrown at internal/database/db.go:2185
return errors.Is(err, gorm.ErrRecordNotFound)
}
func IsSQLiteDB(file io.ReaderAt) (bool, error) {
signature := []byte("SQLite format 3\x00")
buf := make([]byte, len(signature))
_, err := file.ReadAt(buf, 0)
if err != nil {
return false, err
}
return bytes.Equal(buf, signature), nil
}
func BackupSQLite(dstPath string) (err error) {
if IsPostgres() {
return errors.New("sqlite backup is unavailable for PostgreSQL")
}
if db == nil {
return errors.New("database is not initialized")
}
if _, err := os.Lstat(dstPath); err == nil {
return fmt.Errorf("sqlite backup destination already exists: %s", dstPath)
} else if !errors.Is(err, os.ErrNotExist) {
return err
}
defer func() {
if err != nil {
_ = os.Remove(dstPath)
}
}()
ctx, cancel := context.WithTimeout(context.Background(), backupSQLiteTimeout)
defer cancel()
sourceDB, err := db.DB()
if err != nil {
return errView on GitHub (pinned to ad32144c42)
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
Defensive patterns
Strategy: validation
Validate before calling
if database.GetDB() == nil { // or expose an IsInitialized check
return errors.New("init database before backup")
} Try / catch
if err := database.BackupSQLite(dst); err != nil {
if strings.Contains(err.Error(), "not initialized") {
log.Fatal("InitDB must run before BackupSQLite — check boot order")
}
return err
} Prevention
- 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)
When it happens
Trigger: 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.
Common situations: Custom tooling or tests that link the database package and call backup directly; startup races where a job fires before InitDB completes.
Related errors
- sqlite backup is unavailable for PostgreSQL
- sqlite backup destination already exists: %s
- sqlite integrity check failed: %s
- traffic writer queue full
- source sqlite not found at %s: %w
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/eaba4d366b800635.
Report an issue: GitHub.