juanfont/headscale · error

loading nodes: %w

Error message

loading nodes: %w

What it means

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).

Source

Thrown at cmd/headscale/cli/policy.go:214

		if err != nil {
			return fmt.Errorf("reading policy file: %w", err)
		}

		if bypass, _ := cmd.Flags().GetBool(bypassFlag); bypass {
			d, err := openBypassDB(cmd)
			if err != nil {
				return err
			}
			defer d.Close()

			users, err := d.ListUsers(nil)
			if err != nil {
				return fmt.Errorf("loading users: %w", err)
			}

			nodes, err := d.ListNodes()
			if err != nil {
				return fmt.Errorf("loading nodes: %w", err)
			}

			// [policy.NewPolicyManager] validates structure and user references
			// but intentionally skips test evaluation (boot path).
			// [policy.PolicyManager.SetPolicy] is the user-write boundary and is what runs the
			// tests and sshTests blocks.
			pm, err := policy.NewPolicyManager(policyBytes, users, nodes.ViewSlice())
			if err != nil {
				return fmt.Errorf("parsing policy file: %w", err)
			}

			_, err = pm.SetPolicy(policyBytes)
			if err != nil {
				return err
			}

			fmt.Println("Policy is valid")

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Stop headscale, then re-run the check.
  2. Cross-check with `headscale nodes list` over the API once the server is up.
  3. Inspect the wrapped SQL error for the failing table; re-run migrations if the schema is behind.
  4. Restore the database from a known-good backup if corruption is indicated.
Defensive patterns

Strategy: validation

Try / catch

nodes, err := d.ListNodes()
if err != nil {
    if isCorrupt(err) { // e.g. 'database disk image is malformed'
        // restore from backup, then re-run check
    }
    return err
}

Prevention

When it happens

Trigger: Bypass-mode check where the nodes query errors: locked database, corrupt nodes table, migration mismatch between nodes/ip-pool tables.

Common situations: Same as other bypass failures — server running concurrently, partial migration, or a restored/copied database file in an inconsistent state.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/cfbdda60633fb9a2. Report an issue: GitHub.