juanfont/headscale · error · ErrUnsupportedPolicyMode
unsupported policy mode
Error message
unsupported policy mode
What it means
ErrUnsupportedPolicyMode is a sentinel error in hscontrol/state declaring that the configured policy mode is neither "file" nor "db". It is produced by wrapping with the offending mode string (hscontrol/state/debug.go:213: fmt.Errorf("%w: %s", ErrUnsupportedPolicyMode, s.cfg.Policy.Mode)). It surfaces during server startup / debug dumps when the policy.mode config value cannot be mapped to a policy manager backend.
Source
Thrown at hscontrol/state/state.go:66
// defaultRegisterCacheMaxEntries is the default upper bound on the number
// of pending registration entries the auth cache will hold. With a 15-minute
// TTL and a stripped-down RegistrationData payload (~200 bytes per entry),
// 1024 entries cap the worst-case cache footprint at well under 1 MiB even
// under sustained unauthenticated cache-fill attempts.
defaultRegisterCacheMaxEntries = 1024
// defaultNodeStoreBatchSize is the default number of write operations to batch
// before rebuilding the in-memory node snapshot.
defaultNodeStoreBatchSize = 100
// defaultNodeStoreBatchTimeout is the default maximum time to wait before
// processing a partial batch of node operations.
defaultNodeStoreBatchTimeout = 500 * time.Millisecond
)
// ErrUnsupportedPolicyMode is returned for invalid policy modes. Valid modes are "file" and "db".
var ErrUnsupportedPolicyMode = errors.New("unsupported policy mode")
// ErrNodeNotFound is returned when a node cannot be found by its ID.
var ErrNodeNotFound = errors.New("node not found")
// ErrInvalidNodeView is returned when an invalid node view is provided.
var ErrInvalidNodeView = errors.New("invalid node view provided")
// ErrNodeNotInNodeStore is returned when a node no longer exists in the [NodeStore].
var ErrNodeNotInNodeStore = errors.New("node no longer exists in NodeStore")
// ErrNodeNameNotUnique is returned when a node name is not unique.
var ErrNodeNameNotUnique = errors.New("node name is not unique")
// nodeUpdateColumns lists all Node columns that should be written
// during a struct-based GORM Updates() call. Listing them explicitly
// forces GORM to include nil/zero-value fields (e.g. UserID=nil when
// converting a user-owned node to tagged) that struct-based Updates()
// would otherwise silently skip.View on GitHub (pinned to 565fd254d0)
Solutions
- Set policy.mode to "file" if the ACL policy lives in a HuJSON/JSON file referenced by policy.path
- Set policy.mode to "db" if policies are managed via the API/database
- Verify there is no YAML typo or stray whitespace in the policy.mode value
- After fixing, restart headscale and confirm startup logs no longer report the error
Example fix
# before policy: mode: database # after policy: mode: db
Defensive patterns
Strategy: validation
Validate before calling
validModes := map[string]bool{"file": true, "db": true}
if !validModes[cfg.Policy.Mode] {
return fmt.Errorf("invalid policy mode %q: use file or db", cfg.Policy.Mode)
} Type guard
null
Try / catch
null
Prevention
- Validate policy.mode against {file, db} in config linting or CI before deploying
- Pin config templates reviewed on headscale version upgrades since policy keys have changed across releases
When it happens
Trigger: Setting policy.mode in the headscale config to anything other than "file" or "db" (e.g. "database", "acl", typo like "filE"), then triggering the code path in hscontrol/state/debug.go:213 that formats the active policy for a debug dump.
Common situations: Upgrading from older headscale versions where policy config keys changed; copy-pasting configs from tutorials that use invalid mode names; leaving a placeholder value in policy.mode.
Related errors
- STUN address not set
- initial DERPMap is empty, Headscale requires at least one en
- database type not supported
- invalid action
- autogroup:self requires per-node resolution and cannot be re
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/b75332c98a23df4c.
Report an issue: GitHub.