{"record":{"id":"1d67a2cda8b2f10a","repo":"juanfont/headscale","slug":"w-s-1d67a2","errorCode":null,"errorMessage":"%w: %s","messagePattern":"%w: %s","errorType":"validation","errorClass":"ErrInvalidJournalMode","httpStatus":null,"severity":"error","filePath":"hscontrol/db/sqliteconfig/config.go","lineNumber":322,"sourceCode":"\treturn &Config{\n\t\tPath:              \":memory:\",\n\t\tWALAutocheckpoint: -1, // not set, use driver default\n\t\tForeignKeys:       true,\n\t}\n}\n\n// Validate checks if all configuration values are valid.\nfunc (c *Config) Validate() error {\n\tif c.Path == \"\" {\n\t\treturn ErrPathEmpty\n\t}\n\n\tif c.BusyTimeout < 0 {\n\t\treturn fmt.Errorf(\"%w, got %d\", ErrBusyTimeoutNegative, c.BusyTimeout)\n\t}\n\n\tif c.JournalMode != \"\" && !c.JournalMode.IsValid() {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrInvalidJournalMode, c.JournalMode)\n\t}\n\n\tif c.AutoVacuum != \"\" && !c.AutoVacuum.IsValid() {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrInvalidAutoVacuum, c.AutoVacuum)\n\t}\n\n\tif c.WALAutocheckpoint < -1 {\n\t\treturn fmt.Errorf(\"%w, got %d\", ErrWALAutocheckpoint, c.WALAutocheckpoint)\n\t}\n\n\tif c.Synchronous != \"\" && !c.Synchronous.IsValid() {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrInvalidSynchronous, c.Synchronous)\n\t}\n\n\tif c.TxLock != \"\" && !c.TxLock.IsValid() {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrInvalidTxLock, c.TxLock)\n\t}\n","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/db/sqliteconfig/config.go#L304-L340","documentation":"Config.Validate rejected the configured SQLite journal_mode: the value is non-empty but not one of the valid JournalMode pragma values (WAL, DELETE, TRUNCATE, PERSIST, MEMORY, OFF). The sentinel ErrInvalidJournalMode is wrapped with the bad value. Journal mode controls write concurrency and crash recovery behavior.","triggerScenarios":"Setting JournalMode to something like 'wal' (lowercase), 'WRITE_AHEAD', or 'default' in a sqliteconfig.Config and calling Validate/ToURL. Only exact uppercase pragma strings from the JournalMode constants pass IsValid().","commonSituations":"Lowercase values in YAML/TOML configs that were never uppercased; users copying pragma names from SQLite docs with different spelling; typos.","solutions":["Use one of the exported constants: sqliteconfig.JournalModeWAL (recommended for production), JournalModeDelete, etc.","If loading from a config file, strings.ToUpper the value before assignment.","Leave it empty to accept the driver default."],"exampleFix":"// before\ncfg.JournalMode = sqliteconfig.JournalMode(\"wal\") // fails IsValid()\n\n// after\ncfg.JournalMode = sqliteconfig.JournalModeWAL","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func validJournalMode(v sqliteconfig.JournalMode) bool {\n    switch v {\n    case sqliteconfig.JournalModeWAL,\n        sqliteconfig.JournalModeDelete,\n        sqliteconfig.JournalModeTruncate,\n        sqliteconfig.JournalModePersist,\n        sqliteconfig.JournalModeMemory,\n        sqliteconfig.JournalModeOff:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Use the package's exported constants rather than raw strings.","strings.ToUpper user input before assigning enum-typed config fields.","Treat empty string as 'use default' rather than inventing a 'DEFAULT' value."],"tags":["sqlite","config","validation","pragma"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}