{"record":{"id":"d6716744fb4d076d","repo":"juanfont/headscale","slug":"opening-database-w","errorCode":null,"errorMessage":"opening database: %w","messagePattern":"opening database: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/headscale/cli/policy.go","lineNumber":34,"sourceCode":")\n\nconst (\n\tbypassFlag = \"bypass-server-and-access-database-directly\" //nolint:gosec // not a credential\n)\n\nvar errAborted = errors.New(\"command aborted by user\")\n\n// bypassDatabase opens the database directly, bypassing the running server.\n// The caller must close the returned handle.\nfunc bypassDatabase() (*db.HSDatabase, error) {\n\tcfg, err := types.LoadServerConfig()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"loading config: %w\", err)\n\t}\n\n\td, err := db.NewHeadscaleDatabase(cfg)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"opening database: %w\", err)\n\t}\n\n\treturn d, nil\n}\n\n// openBypassDB confirms the destructive bypass action and opens the database\n// directly. The caller is responsible for closing the returned handle.\nfunc openBypassDB(cmd *cobra.Command) (*db.HSDatabase, error) {\n\tif !confirmAction(cmd, \"DO NOT run this command if an instance of headscale is running, are you sure headscale is not running?\") {\n\t\treturn nil, errAborted\n\t}\n\n\treturn bypassDatabase()\n}\n\nfunc init() {\n\trootCmd.AddCommand(policyCmd)\n","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/headscale/cli/policy.go#L16-L52","documentation":"Thrown by bypassDatabase() when db.NewHeadscaleDatabase() cannot open the configured database. Bypass mode skips the running server and attaches directly to SQLite/PostgreSQL; failure means the connection string, driver, permissions, or schema state prevented a usable handle.","triggerScenarios":"`policy get/set/check --bypass...` with a SQLite file that does not exist or is not writable; PostgreSQL refused connection (wrong host/port/credentials); database file locked by a running headscale instance; migrations failing to apply on open.","commonSituations":"Running bypass against a database while headscale is running (SQLite lock); config's database section pointing at a stale path; Postgres TLS/auth mismatch; read-only filesystem (container, snap).","solutions":["Ensure headscale is NOT running (the command warns about this for a reason): `systemctl stop headscale` first.","Check the database.path / postgres settings in the config the CLI just loaded.","Verify file permissions on the SQLite file for the user running the CLI.","For PostgreSQL, test connectivity with psql using the same DSN."],"exampleFix":"# before: bypass while server is running (SQLite locked)\nheadscale policy set --file p.hujson --bypass-server-and-access-database-directly\n\n# after\nsudo systemctl stop headscale\nheadscale policy set --file p.hujson --bypass-server-and-access-database-directly\nsudo systemctl start headscale","handlingStrategy":"validation","validationCode":"// refuse to bypass while the server holds the database (SQLite case)\nfunc ensureHeadscaleStopped(dbPath string) error {\n    if err := exec.Command(\"fuser\", dbPath).Run(); err == nil {\n        return fmt.Errorf(\"another process holds %s — stop headscale first\", dbPath)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"d, err := bypassDatabase()\nif err != nil {\n    if strings.Contains(err.Error(), \"opening database\") {\n        // likely lock/permissions: stop service, fix perms, retry once\n    }\n    return err\n}","preventionTips":["Stop the headscale service before any --bypass command; script it as stop -> command -> start.","Keep database file ownership consistent with the user running the CLI.","For PostgreSQL, verify the DSN with psql before automation uses bypass mode."],"tags":["database","cli","bypass","sqlite","postgres"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}