{"record":{"id":"92e2fd13e4d5850f","repo":"juanfont/headscale","slug":"loading-config-w","errorCode":null,"errorMessage":"loading config: %w","messagePattern":"loading config: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/headscale/cli/policy.go","lineNumber":29,"sourceCode":"\t\"github.com/juanfont/headscale/hscontrol/db\"\n\t\"github.com/juanfont/headscale/hscontrol/policy\"\n\t\"github.com/juanfont/headscale/hscontrol/types\"\n\t\"github.com/spf13/cobra\"\n\t\"tailscale.com/types/views\"\n)\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()","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/headscale/cli/policy.go#L11-L47","documentation":"Thrown by bypassDatabase() in the policy CLI commands when types.LoadServerConfig() fails. Bypass mode (--bypass-server-and-access-database-directly) opens the database directly, which first requires loading the server configuration file from disk. The wrapped error names the config file and the parse failure.","triggerScenarios":"Running `headscale policy get/set/check --bypass-server-and-access-database-directly` when the configuration file does not exist at the expected path, is unreadable, or contains invalid YAML. Also triggered by config keys with invalid values (bad duration, unknown enum).","commonSituations":"Running the CLI from a directory other than where headscale config lives without setting the config path flag/env; config migrated between headscale versions with renamed keys; permissions on /etc/headscale/config.yaml; leftover BOM or tabs breaking YAML parsing.","solutions":["Pass the config explicitly: `headscale --config /etc/headscale/config.yaml policy ...` or set HEADSCALE_CONFIG_PATH.","Read the wrapped error — it names the exact file and YAML problem (line/column).","Validate the file parses: `headscale config view` (non-bypass path uses the same loader).","If keys were renamed in an upgrade, re-check the config reference in docs/ for your version."],"exampleFix":"# before\nheadscale policy get --bypass-server-and-access-database-directly\n\n# after\nheadscale --config /etc/headscale/config.yaml policy get --bypass-server-and-access-database-directly","handlingStrategy":"validation","validationCode":"// before running a bypass command, assert the config exists and parses\nfunc checkConfig(path string) error {\n    fi, err := os.Stat(path)\n    if err != nil {\n        return fmt.Errorf(\"config missing: %w\", err)\n    }\n    if fi.IsDir() {\n        return fmt.Errorf(\"config path is a directory: %s\", path)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if _, err := os.Stat(cfgPath); err != nil {\n    log.Fatalf(\"config check failed: %v — pass --config explicitly\", err)\n}","preventionTips":["Always invoke the CLI with an explicit --config in scripts and cron jobs.","Set HEADSCALE_CONFIG_PATH in service definitions.","After upgrading headscale, run a config-parse smoke test (headscale config view) before automation depends on it."],"tags":["config","cli","database","bypass"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}