juanfont/headscale · error

%w: group %q got %T

Error message

%w: group %q got %T

What it means

A groups entry's value is neither an array nor a string — it is a number, object, boolean, or null (ErrGroupValueNotArray). The message reports the Go type seen.

Source

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

	for key, value := range rawMap {
		switch v := value.(type) {
		case []any:
			// Convert []interface{} to []string
			var stringSlice []string

			for _, item := range v {
				if str, ok := item.(string); ok {
					stringSlice = append(stringSlice, str)
				} else {
					return fmt.Errorf("%w: group %q expected string but got %T", ErrInvalidGroupMember, key, item)
				}
			}

			rawGroups[key] = stringSlice
		case string:
			return fmt.Errorf("%w: group %q got string: %q", ErrGroupValueNotArray, key, v)
		default:
			return fmt.Errorf("%w: group %q got %T", ErrGroupValueNotArray, key, v)
		}
	}

	// Reject group-in-group references. Reverse-sort the keys so the
	// reported (parent, child) pair names the deepest non-leaf parent
	// first.
	keys := make([]string, 0, len(rawGroups))
	for k := range rawGroups {
		keys = append(keys, k)
	}

	slices.Sort(keys)
	slices.Reverse(keys)

	for _, key := range keys {
		for _, u := range rawGroups[key] {
			if isGroup(u) {
				return fmt.Errorf("groups[%q]: %q: %w", key, u, ErrGroupMembersCannotBeRecursive)

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Make every groups value an array of username strings
  2. Delete null placeholder entries entirely

Example fix

// before
{"group:eng": null}
// after
{"group:eng": ["dev@example.com"]}
Defensive patterns

Strategy: type-guard

Type guard

func groupValueShapeOk(v any) bool {
	switch v.(type) {
	case []any, string: return true
	default: return false
	}
}

Prevention

When it happens

Trigger: Writing "group:x": 5, {"group:x": {}}, or "group:x": null in the groups map.

Common situations: Programmatic policy generation with wrong types, or commented-out values collapsing to null in JSON.

Related errors


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