{"record":{"id":"a09e6beed162f907","repo":"JuliusBrussee/caveman","slug":"open-sqlite-q-w-a09e6b","errorCode":null,"errorMessage":"open sqlite %q: %w","messagePattern":"open sqlite %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"proxy/internal/store/store.go","lineNumber":268,"sourceCode":"// client's ORIGINAL bytes for a frozen block it already compressed, flipping the\n// upstream prefix mid-conversation.\nfunc sqliteDSN(path string) string {\n\tconst pragmas = \"_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)\"\n\tif path == \":memory:\" {\n\t\treturn \"file::memory:?\" + pragmas\n\t}\n\t// A file: URI so a path containing '?' or '#' cannot be truncated into a\n\t// different database file by the driver's DSN split.\n\tu := url.URL{Scheme: \"file\", OmitHost: true, Path: path}\n\treturn u.String() + \"?\" + pragmas\n}\n\n// Open opens (creating if needed) the SQLite database at path and migrates the\n// schema. logger may be nil.\nfunc Open(path string, logger *slog.Logger) (*Store, error) {\n\tdb, err := sql.Open(\"sqlite\", sqliteDSN(path))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"open sqlite %q: %w\", path, err)\n\t}\n\tif _, err := db.Exec(schema); err != nil {\n\t\t_ = db.Close()\n\t\treturn nil, fmt.Errorf(\"migrate sqlite %q: %w\", path, err)\n\t}\n\tif path != \":memory:\" {\n\t\t_ = os.Chmod(path, 0o600)\n\t}\n\tfor _, m := range migrations {\n\t\tif _, err := db.Exec(m); err != nil && !strings.Contains(err.Error(), \"duplicate column name\") {\n\t\t\t_ = db.Close()\n\t\t\treturn nil, fmt.Errorf(\"migrate sqlite %q: %w\", path, err)\n\t\t}\n\t}\n\treturn &Store{db: db, logger: logger}, nil\n}\n\n// Close closes the underlying database.","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/proxy/internal/store/store.go#L250-L286","documentation":"Returned by store.Open when sql.Open(\"sqlite\", DSN) itself fails. With modernc.org/sqlite this is almost never a file problem (opening is lazy) — it means the driver name is not registered (blank import missing), the DSN pragmas are malformed, or the pure-Go driver failed to initialize.","triggerScenarios":"Calling store.Open in a binary that does not blank-import the sqlite driver registration (or links an incompatible driver version); a DSN whose query string of pragmas is syntactically rejected; a driver/runtime incompatibility (e.g. modernc.org/sqlite requires specific Go versions).","commonSituations":"Splitting the store package into a new binary and forgetting the driver's blank import; go.mod tidying away the driver because only a blank import references it; upgrading modernc.org/sqlite to a version needing a newer Go toolchain; building for GOOS/GOARCH the pure-Go driver does not support.","solutions":["Ensure the sqlite driver is registered: import _ \"modernc.org/sqlite\" in the binary (or keep it in store's imports as Open expects)","Run go mod tidy and pin a modernc.org/sqlite version compatible with your Go toolchain","Verify the DSN builder (file: URI + pragmas) was not modified into an invalid query string","Check GOOS/GOARCH support for the cgo-free driver if cross-compiling"],"exampleFix":"// before: new cmd binary uses store.Open but never registers the driver\nimport \"proxy/internal/store\"\n\n// after\nimport (\n    \"proxy/internal/store\"\n    _ \"modernc.org/sqlite\"\n)","handlingStrategy":"validation","validationCode":"// Before Open, confirm the driver registers (cheap smoke check at startup)\nif _, ok := sql.Open(\"sqlite\", \":memory:\").(*sql.DB); !ok {\n    panic(\"sqlite driver not registered\")\n}","typeGuard":null,"tryCatchPattern":"st, err := store.Open(path, logger)\nif err != nil {\n    if strings.Contains(err.Error(), \"open sqlite\") {\n        // driver/DSN problem: check blank import of modernc.org/sqlite and go.mod\n        log.Error(\"sqlite driver unavailable; rebuild with the driver linked in\", \"error\", err)\n    }\n}","preventionTips":["Blank-import _ \"modernc.org/sqlite\" in every binary that calls store.Open","Run go mod tidy after driver version changes; keep driver and Go toolchain compatible","Add a startup smoke test that opens :memory: via the same helper"],"tags":["sqlite","driver-registration","build","go"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}