{"record":{"id":"20d44b69b272b10e","repo":"juanfont/headscale","slug":"setting-acl-policy-w","errorCode":null,"errorMessage":"setting ACL policy: %w","messagePattern":"setting ACL policy: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/headscale/cli/policy.go","lineNumber":154,"sourceCode":"\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\tusers, err := d.ListUsers(nil)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"loading users for policy validation: %w\", err)\n\t\t\t}\n\n\t\t\t_, err = policy.NewPolicyManager(policyBytes, users, views.Slice[types.NodeView]{})\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"parsing policy file: %w\", err)\n\t\t\t}\n\n\t\t\t_, err = d.SetPolicy(string(policyBytes))\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"setting ACL policy: %w\", err)\n\t\t\t}\n\t\t} else {\n\t\t\tpolicyStr := string(policyBytes)\n\n\t\t\terr := withClient(func(ctx context.Context, client *clientv1.ClientWithResponses) error {\n\t\t\t\tresp, err := client.SetPolicyWithResponse(ctx, clientv1.SetPolicyJSONRequestBody{\n\t\t\t\t\tPolicy: &policyStr,\n\t\t\t\t})\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"setting 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\treturn nil\n\t\t\t})","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/headscale/cli/policy.go#L136-L172","documentation":"Thrown in `headscale policy set --bypass...` when d.SetPolicy() fails writing the validated policy into the database. Because the CLI already ran NewPolicyManager successfully, this is a persistence-layer failure (write/transaction), not a policy-content failure.","triggerScenarios":"SQLite database locked by another process; disk full; transaction aborted; database opened read-only. The policy content has already passed validation at this point.","commonSituations":"headscale was started again between the confirmation prompt and the write; low disk on the volume holding the SQLite file; container with a read-only mount.","solutions":["Confirm headscale is stopped and no other process holds the database.","Check disk space on the database volume.","Retry the command — the write is a single transaction and idempotent.","If it persists, inspect SQLite lock state (`fuser <db>`, `lsof <db>`)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := d.SetPolicy(string(policyBytes)); err != nil {\n    if isLocked(err) || isBusy(err) {\n        // ensure server stopped, then retry once\n    }\n    return err\n}","preventionTips":["Single-writer discipline: only one bypass command at a time, server stopped.","Check disk space before policy writes in constrained environments.","Back up the database before policy-changing bypass operations."],"tags":["database","policy","cli","bypass"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}