{"record":{"id":"74ba8b33fe7fb6c0","repo":"juanfont/headscale","slug":"loading-policy-from-database-w","errorCode":null,"errorMessage":"loading policy from database: %w","messagePattern":"loading policy from database: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/headscale/cli/policy.go","lineNumber":88,"sourceCode":"}\n\nvar getPolicy = &cobra.Command{\n\tUse:     \"get\",\n\tShort:   \"Print the current ACL Policy\",\n\tAliases: []string{cmdShow, \"view\", \"fetch\"},\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tvar policyData string\n\n\t\tif bypass, _ := cmd.Flags().GetBool(bypassFlag); bypass {\n\t\t\td, err := openBypassDB(cmd)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer d.Close()\n\n\t\t\tpol, err := d.GetPolicy()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"loading policy from database: %w\", err)\n\t\t\t}\n\n\t\t\tpolicyData = pol.Data\n\t\t} else {\n\t\t\terr := withClient(func(ctx context.Context, client *clientv1.ClientWithResponses) error {\n\t\t\t\tresp, err := client.GetPolicyWithResponse(ctx)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"loading ACL policy: %w\", err)\n\t\t\t\t}\n\n\t\t\t\tif resp.StatusCode() != http.StatusOK {\n\t\t\t\t\treturn apiError(resp.StatusCode(), resp.ApplicationproblemJSONDefault)\n\t\t\t\t}\n\n\t\t\t\tpolicyData = resp.JSON200.Policy\n\n\t\t\t\treturn nil\n\t\t\t})","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/headscale/cli/policy.go#L70-L106","documentation":"Thrown in `headscale policy get` bypass mode when d.GetPolicy() fails on the directly-opened database. The policy row is stored in the database (acl_policy_path must be empty / db mode); the read failed at the SQL layer or no usable policy row exists.","triggerScenarios":"`policy get --bypass...` where the database was never initialized with a policy row, the table is missing (very old database not migrated), or the SQL query errors (locked/corrupt DB).","commonSituations":"Instance that always used file-based policy (acl_policy_path set) so the db policy table was never populated; interrupted migration leaving the schema half-applied; opening a non-headscale SQLite file by mistake.","solutions":["Confirm the instance actually runs in database policy mode (acl_policy_path empty in config).","If file mode was intended, run `policy get` WITHOUT the bypass flag only after switching modes; otherwise read the HuJSON file directly.","Run `headscale db migrate`-equivalent / check migration status to ensure the policy table exists.","If a fresh policy is acceptable, use `policy set --bypass...` to seed the row."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"pol, err := d.GetPolicy()\nif err != nil {\n    if isNoPolicyRow(err) { // sql.ErrNoRows or equivalent\n        // db policy mode never initialised: seed via policy set, or switch to file mode\n    }\n    return err\n}","preventionTips":["Decide policy mode (file vs db) once at setup and keep acl_policy_path consistent with it.","After major upgrades, run policy get once to confirm the row survives migrations.","Document which mode your deployment uses — mixed mode is the usual root cause."],"tags":["database","policy","cli","bypass"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}