{"record":{"id":"35b7bce7f56c33b1","repo":"wavetermdev/waveterm","slug":"opening-db-w","errorCode":null,"errorMessage":"opening db: %w","messagePattern":"opening db: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/filestore/blockstore_dbsetup.go","lineNumber":70,"sourceCode":"func GetDBName() string {\n\twaveHome := wavebase.GetWaveDataDir()\n\treturn filepath.Join(waveHome, wavebase.WaveDBDir, FilestoreDBName)\n}\n\nfunc MakeDB(ctx context.Context) (*sqlx.DB, error) {\n\tvar rtn *sqlx.DB\n\tvar err error\n\tif useTestingDb {\n\t\tdbName := \":memory:\"\n\t\tlog.Printf(\"[db] using in-memory db\\n\")\n\t\trtn, err = sqlx.Open(\"sqlite3\", dbName)\n\t} else {\n\t\tdbName := GetDBName()\n\t\tlog.Printf(\"[db] opening db %s\\n\", dbName)\n\t\trtn, err = sqlx.Open(\"sqlite3\", fmt.Sprintf(\"file:%s?mode=rwc&_journal_mode=WAL&_busy_timeout=5000\", dbName))\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"opening db: %w\", err)\n\t}\n\trtn.DB.SetMaxOpenConns(1)\n\treturn rtn, nil\n}\n\nfunc WithTx(ctx context.Context, fn func(tx *TxWrap) error) error {\n\treturn txwrap.WithTx(ctx, globalDB, fn)\n}\n\nfunc WithTxRtn[RT any](ctx context.Context, fn func(tx *TxWrap) (RT, error)) (RT, error) {\n\treturn txwrap.WithTxRtn(ctx, globalDB, fn)\n}\n","sourceCodeStart":52,"sourceCodeEnd":83,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/filestore/blockstore_dbsetup.go#L52-L83","documentation":"MakeDB opens the filestore's SQLite database with sqlx.Open using the go-sqlite3 driver, either an in-memory db (testing) or the WAL-mode file db under the Wave data directory. sqlx.Open validates the driver name and DSN and can fail before any connection is made; this error wraps that failure. Note sqlx.Open is lazy — later connection failures surface on first use, so this error usually indicates a DSN/driver-level problem, while actual file-open errors (bad path, permissions) may appear at first query.","triggerScenarios":"sqlite3 driver not registered (blank import of github.com/mattn/go-sqlite3 missing); malformed DSN from GetDBName(); in tests, useTestingDb path failing to open ':memory:'. Path/permission problems on the db file typically surface later at first query rather than here.","commonSituations":"App startup via InitFilestore failing because WAVE_DATA_DIR path contains characters that break the file: DSN (e.g. '?' or '#'); building with a sqlite driver variant that registers a different name; misconfigured data directory.","solutions":["Ensure github.com/mattn/go-sqlite3 is imported (blank import) so the 'sqlite3' driver is registered.","Verify the DSN: log GetDBName() and check the data dir exists and the path has no characters that break the file: URI (encode with url.PathEscape if needed).","Confirm WAVE_DATA_DIR is writable by the running user; create the dir if missing.","If using CGO_ENABLED=0 builds, mattn/go-sqlite3 will not work — use a pure-Go driver or enable CGO.","Since Open is lazy, also wrap the first query/migration errors; make sure migration errors in InitFilestore are not being mistaken for this one."],"exampleFix":"// before\nimport (\n    _ \"github.com/mattn/go-sqlite3\"\n    \"github.com/jmoiron/sqlx\"\n)\n// after\nimport (\n    _ \"github.com/mattn/go-sqlite3\" // must remain: registers the \"sqlite3\" driver\n    \"github.com/jmoiron/sqlx\"\n)\n// and validate the dir before MakeDB:\nif err := os.MkdirAll(filepath.Dir(GetDBName()), 0o755); err != nil {\n    return fmt.Errorf(\"db dir missing: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"import (\n    \"database/sql\"\n    _ \"github.com/mattn/go-sqlite3\"\n)\nfunc sqliteDriverAvailable() bool {\n    for _, d := range sql.Drivers() {\n        if d == \"sqlite3\" {\n            return true\n        }\n    }\n    return false\n}","typeGuard":null,"tryCatchPattern":"db, err := MakeDB(ctx)\nif err != nil {\n    return fmt.Errorf(\"filestore init failed: %w\", err)\n}\n// Open is lazy: force a real connection to surface path/permission errors now\nif err := db.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"db not reachable: %w\", err)\n}","preventionTips":["Keep the blank import of go-sqlite3 in the binary (watch for it being dropped in refactors)","Ensure the data dir exists and is writable before InitFilestore","Avoid special characters (?#) in the data dir path or escape the DSN","Do not build with CGO_ENABLED=0 when using mattn/go-sqlite3","Ping the db immediately after MakeDB to convert lazy failures into early, clear errors"],"tags":["sqlite","startup","driver","database"],"backgroundTag":"sqlite-driver-not-registered","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}