juanfont/headscale · error

group must start with 'group:'

Error message

group must start with 'group:'

What it means

Group.Validate (hscontrol/policy/v2/types.go:461) requires every group key to start with the literal prefix 'group:'. The prefix is how the policy grammar distinguishes groups from usernames, tags, and hosts in alias positions, so a key without it fails at UnmarshalJSON time.

Source

Thrown at hscontrol/policy/v2/types.go:111

	ErrNodeAttrTargetUnsupported    = errors.New("nodeAttrs target alias type is not supported")
)

// nodeAttrUnsupportedCaps lists caps that headscale parses but cannot act on
// today. Each entry maps to the tracking issue an operator can follow. The
// caps are accepted by Tailscale SaaS, but delivering them via headscale
// without the matching server-side machinery would be misleading — nodes
// would advertise a feature that does not work. Reject at policy load and
// point operators at the issue.
var nodeAttrUnsupportedCaps = map[tailcfg.NodeCapability]string{
	tailcfg.NodeAttrFunnel: "https://github.com/juanfont/headscale/issues/2527",
}

// Policy validation errors.
var (
	ErrInvalidUsername             = errors.New("username must contain @")
	ErrUserNotFound                = errors.New("user not found")
	ErrMultipleUsersFound          = errors.New("multiple users found")
	ErrInvalidGroupFormat          = errors.New("group must start with 'group:'")
	ErrInvalidTagFormat            = errors.New("tag must start with 'tag:'")
	ErrInvalidHostname             = errors.New("invalid hostname")
	ErrHostResolve                 = errors.New("error resolving host")
	ErrInvalidPrefix               = errors.New("invalid prefix")
	ErrInvalidAutogroup            = errors.New("invalid autogroup")
	ErrUnknownAutogroup            = errors.New("unknown autogroup")
	ErrHostportMissingColon        = errors.New("hostport must contain a colon")
	ErrTypeNotSupported            = errors.New("type not supported")
	ErrInvalidAlias                = errors.New("invalid alias format")
	ErrInvalidAutoApprover         = errors.New("invalid auto approver format")
	ErrInvalidOwner                = errors.New("invalid owner format")
	ErrGroupNotDefined             = errors.New("group not defined in policy")
	ErrInvalidGroupMember          = errors.New("invalid group member type")
	ErrGroupValueNotArray          = errors.New("group value must be an array of users")
	ErrInvalidHostIP               = errors.New("hostname contains invalid IP address")
	ErrTagNotDefined               = errors.New("tag not found")
	ErrAutoApproverNotAlias        = errors.New("auto approver is not an alias")
	ErrInvalidACLAction            = errors.New("invalid ACL action")

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Rename the group key to start with 'group:'
  2. Keep the prefix when referencing the group elsewhere (src/dst/owners)
  3. Run 'headscale policy check' on the file before applying to catch parse errors early

Example fix

// before
{"groups": {"admins": ["alice@example.com"]}}
// after
{"groups": {"group:admins": ["alice@example.com"]}}
Defensive patterns

Strategy: validation

Validate before calling

for key := range policy.Groups {
    if !strings.HasPrefix(key, "group:") {
        return fmt.Errorf("group key %q must start with 'group:'", key)
    }
}

Type guard

func isGroupKey(s string) bool { return strings.HasPrefix(s, "group:") }

Try / catch

if errors.Is(err, policy.ErrInvalidGroupFormat) {
    // rename the key adding the group: prefix
}

Prevention

When it happens

Trigger: Defining {"groups": {"admins": [...]}} instead of {"groups": {"group:admins": [...]}}; also when a group key contains the prefix in the wrong case or position ('Group:admins'). Fails during policy parse, before any resolution.

Common situations: Writing a first ACL file following generic Tailscale examples that omit the prefix; renaming groups and dropping the prefix; JSON key typos after hand-editing.

Related errors


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