{"record":{"id":"28e45ac48a55dbf9","repo":"usememos/memos","slug":"dsn-required","errorCode":null,"errorMessage":"dsn required","messagePattern":"dsn required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"store/db/sqlite/sqlite.go","lineNumber":27,"sourceCode":"\t// Note: modernc.org/sqlite driver is imported in functions.go where\n\t// RegisterScalarFunction is used. No blank import needed here.\n\n\t\"github.com/usememos/memos/internal/profile\"\n\t\"github.com/usememos/memos/store\"\n)\n\ntype DB struct {\n\tdb      *sql.DB\n\tprofile *profile.Profile\n}\n\n// NewDB opens a database specified by its database driver name and a\n// driver-specific data source name, usually consisting of at least a\n// database name and connection information.\nfunc NewDB(profile *profile.Profile) (store.Driver, error) {\n\t// Ensure a DSN is set before attempting to open the database.\n\tif profile.DSN == \"\" {\n\t\treturn nil, errors.New(\"dsn required\")\n\t}\n\n\tif err := ensureUnicodeLowerRegistered(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to register sqlite unicode lower function\")\n\t}\n\n\tif err := ensureRegexpRegistered(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to register sqlite regexp function\")\n\t}\n\n\t// Connect to the database with some sane settings:\n\t// - No shared-cache: it's obsolete; WAL journal mode is a better solution.\n\t// - No foreign key constraints: it's currently disabled by default, but it's a\n\t// good practice to be explicit and prevent future surprises on SQLite upgrades.\n\t// - Journal mode set to WAL: it's the recommended journal mode for most applications\n\t// as it prevents locking issues.\n\t// - mmap size set to 0: it disables memory mapping, which can cause OOM errors on some systems.\n\t//","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/store/db/sqlite/sqlite.go#L9-L45","documentation":"The SQLite driver refuses to open when profile.DSN is empty, before registering custom functions or connecting. Unlike MySQL/Postgres it has no default file path at this layer, so an empty DSN is treated as misconfiguration rather than silently creating a database in an unintended location.","triggerScenarios":"Running memos with --driver sqlite but no --data/-d DSN and no MEMOS_DSN env var; env var name typos; container deployments that forgot to mount/set the data path.","commonSituations":"Docker runs missing the volume or env wiring; CLI scripts that conditionally set DSN but skip the sqlite branch; CI configs that only populate the Postgres DSN.","solutions":["Set the DSN to a writable file path, e.g. MEMOS_DSN=/var/opt/memos/memos_prod.db or pass --data","Verify the parent directory exists and the process user can write it","Check env var spelling if you expected a DSN to be set"],"exampleFix":"# before\ndocker run usememos/memos --driver sqlite\n# after\ndocker run -v memos_data:/var/opt/memos usememos/memos --driver sqlite --data /var/opt/memos/memos_prod.db","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(dsn) == \"\" {\n    log.Fatal(\"sqlite driver requires a DSN file path, e.g. --data /var/opt/memos/memos_prod.db\")\n}","typeGuard":"func hasSQLiteDSN(dsn string) bool { return strings.TrimSpace(dsn) != \"\" }","tryCatchPattern":null,"preventionTips":["Always set an explicit data path for sqlite in containers and CI","Ensure the data directory exists and is writable by the service user"],"tags":["database","sqlite","dsn","startup"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}