{"record":{"id":"0478388ad9ffd6ec","repo":"MHSanaei/3x-ui","slug":"xui-db-type-postgres-but-xui-db-dsn-is-empty","errorCode":null,"errorMessage":"XUI_DB_TYPE=postgres but XUI_DB_DSN is empty","messagePattern":"XUI_DB_TYPE=postgres but XUI_DB_DSN is empty","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/database/db.go","lineNumber":1986,"sourceCode":"\t\t\tlog.New(os.Stdout, \"\\r\\n\", log.LstdFlags),\n\t\t\tlogger.Config{\n\t\t\t\tSlowThreshold:             time.Second,\n\t\t\t\tLogLevel:                  logger.Info,\n\t\t\t\tIgnoreRecordNotFoundError: true,\n\t\t\t\tColorful:                  true,\n\t\t\t},\n\t\t)\n\t} else {\n\t\tgormLogger = logger.Discard\n\t}\n\tc := &gorm.Config{Logger: gormLogger, DisableForeignKeyConstraintWhenMigrating: true}\n\n\tvar err error\n\tswitch config.GetDBKind() {\n\tcase \"postgres\":\n\t\tdsn := config.GetDBDSN()\n\t\tif dsn == \"\" {\n\t\t\treturn errors.New(\"XUI_DB_TYPE=postgres but XUI_DB_DSN is empty\")\n\t\t}\n\t\tdb, err = openPostgresWithRetry(dsn, c)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\tdefault:\n\t\tdir := path.Dir(dbPath)\n\t\tif err = os.MkdirAll(dir, 0o755); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err = cleanupSQLiteBackupDirs(filepath.Dir(dbPath)); err != nil {\n\t\t\tlog.Printf(\"clean SQLite backup directories: %v\", err)\n\t\t}\n\n\t\tsync := sqliteSynchronous()\n\t\tjournal := sqliteJournalMode()\n\t\tdsn := dbPath + \"?_journal_mode=\" + journal + \"&_busy_timeout=10000&_synchronous=\" + sync + \"&_txlock=immediate\"\n\t\tdb, err = gorm.Open(sqlite.Open(dsn), c)","sourceCodeStart":1968,"sourceCodeEnd":2004,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/database/db.go#L1968-L2004","documentation":"InitDB refuses to continue when config.GetDBKind() returns 'postgres' but the DSN environment variable XUI_DB_DSN is empty. PostgreSQL has no default DSN in this codebase, so there is nothing to connect to; failing fast prevents GORM from attempting a meaningless connection loop. This is a startup-time configuration validation error.","triggerScenarios":"Setting XUI_DB_TYPE=postgres without XUI_DB_DSN in /etc/default/x-ui (or the systemd unit env); typo'ing the DSN variable name; exporting XUI_DB_TYPE in a shell but forgetting the DSN when running ./x-ui or the migration subcommand.","commonSituations":"Migrating a panel from SQLite to Postgres per the documented flow; CI jobs that set only the DB type; docker deployments missing the -e XUI_DB_DSN flag.","solutions":["Set XUI_DB_DSN to a full libpq/pq URL, e.g. postgres://user:pass@host:5432/xui?sslmode=disable","Verify with: XUI_DB_TYPE=postgres XUI_DB_DSN=... ./x-ui migrate-db or just restart the service","If Postgres was not intended, unset XUI_DB_TYPE to fall back to SQLite at /etc/x-ui/x-ui.db"],"exampleFix":"# before\nXUI_DB_TYPE=postgres\n\n# after\nXUI_DB_TYPE=postgres\nXUI_DB_DSN=postgres://xui:secret@db.internal:5432/xui?sslmode=require","handlingStrategy":"validation","validationCode":"if os.Getenv(\"XUI_DB_TYPE\") == \"postgres\" && os.Getenv(\"XUI_DB_DSN\") == \"\" {\n    log.Fatal(\"XUI_DB_DSN is required when XUI_DB_TYPE=postgres\")\n}","typeGuard":null,"tryCatchPattern":"if err := database.InitDB(dbPath); err != nil {\n    if strings.Contains(err.Error(), \"XUI_DB_DSN is empty\") {\n        log.Fatal(\"set XUI_DB_DSN, e.g. postgres://user:pass@host:5432/xui\")\n    }\n    log.Fatal(err)\n}","preventionTips":["Set XUI_DB_TYPE and XUI_DB_DSN together in /etc/default/x-ui","Add a preflight check in deploy scripts that fails when type=postgres and DSN is unset","Test the DSN with psql before starting the panel"],"tags":["database","postgres","configuration","startup"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}