{"record":{"id":"cfbdda60633fb9a2","repo":"juanfont/headscale","slug":"loading-nodes-w","errorCode":null,"errorMessage":"loading nodes: %w","messagePattern":"loading nodes: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/headscale/cli/policy.go","lineNumber":214,"sourceCode":"\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"reading policy file: %w\", err)\n\t\t}\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\tusers, err := d.ListUsers(nil)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"loading users: %w\", err)\n\t\t\t}\n\n\t\t\tnodes, err := d.ListNodes()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"loading nodes: %w\", err)\n\t\t\t}\n\n\t\t\t// [policy.NewPolicyManager] validates structure and user references\n\t\t\t// but intentionally skips test evaluation (boot path).\n\t\t\t// [policy.PolicyManager.SetPolicy] is the user-write boundary and is what runs the\n\t\t\t// tests and sshTests blocks.\n\t\t\tpm, err := policy.NewPolicyManager(policyBytes, users, nodes.ViewSlice())\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 = pm.SetPolicy(policyBytes)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tfmt.Println(\"Policy is valid\")\n","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/headscale/cli/policy.go#L196-L232","documentation":"Thrown in `headscale policy check --bypass...` when d.ListNodes() fails after users were loaded successfully. Nodes are needed so the policy can be validated against real machines (tag owners, hostnames, tests referencing nodes).","triggerScenarios":"Bypass-mode check where the nodes query errors: locked database, corrupt nodes table, migration mismatch between nodes/ip-pool tables.","commonSituations":"Same as other bypass failures — server running concurrently, partial migration, or a restored/copied database file in an inconsistent state.","solutions":["Stop headscale, then re-run the check.","Cross-check with `headscale nodes list` over the API once the server is up.","Inspect the wrapped SQL error for the failing table; re-run migrations if the schema is behind.","Restore the database from a known-good backup if corruption is indicated."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"nodes, err := d.ListNodes()\nif err != nil {\n    if isCorrupt(err) { // e.g. 'database disk image is malformed'\n        // restore from backup, then re-run check\n    }\n    return err\n}","preventionTips":["Keep database backups; test restore before you need it.","Run PRAGMA integrity_check on a schedule for SQLite deployments.","Complete migrations in full before running bypass tools."],"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"}