weaviate/weaviate · error

role %q in 'includeRoles' is a built-in role and cannot be b

Error message

role %q in 'includeRoles' is a built-in role and cannot be backed up

What it means

A built-in role (from authorization.BuiltInRoles, e.g. roles shipped with Weaviate like admin/viewer) was explicitly named in 'includeRoles'. Built-in roles cannot be included in a backup because restore re-applies built-ins from env and code anyway; including them would be redundant and misleading. Wildcards are safe — they expand over custom roles only — so this only fires on explicit naming.

Source

Thrown at usecases/backup/scheduler.go:833

		return nil, fmt.Errorf("list all roles: %w", err)
	}
	return resolveRoleSelectors(includeRoles, allRoles)
}

// resolveRoleSelectors follows resolveUserSelectors: '*'/'?' wildcards, dedup,
// exact selectors must exist, and a non-empty list matching nothing is an error.
//
// Built-in roles are the exception. Naming one explicitly is rejected, and
// wildcards expand over custom roles only, so '*' never picks up a built-in.
// Restore re-applies the built-ins from env and code either way.
func resolveRoleSelectors(includeRoles, allRoles []string) ([]string, error) {
	if dup := findDuplicate(includeRoles); dup != "" {
		return nil, fmt.Errorf("role list 'includeRoles' contains duplicate: %s", dup)
	}

	for _, r := range includeRoles {
		if slices.Contains(authorization.BuiltInRoles, r) {
			return nil, fmt.Errorf("role %q in 'includeRoles' is a built-in role and cannot be backed up", r)
		}
	}

	candidates := make([]string, 0, len(allRoles))
	for _, r := range allRoles {
		if slices.Contains(authorization.BuiltInRoles, r) {
			continue
		}
		candidates = append(candidates, r)
	}

	roles := expandWildcards(includeRoles, candidates)

	known := make(map[string]struct{}, len(candidates))
	for _, r := range candidates {
		known[r] = struct{}{}
	}
	for _, r := range roles {

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Remove built-in role names from includeRoles; keep only custom roles.
  2. To snapshot all custom roles, use the '*' wildcard — it expands over custom roles only and never picks up built-ins.
  3. No client-side change needed for built-ins on restore: the restore process re-applies built-ins from env and code automatically.

Example fix

// before
{"includeRoles": ["admin", "viewer", "analytics-role"]}
// after
{"includeRoles": ["analytics-role"]}  // or ["*"] for all custom roles
Defensive patterns

Strategy: validation

Validate before calling

import "slices"
for _, r := range includeRoles {
    if slices.Contains(authorization.BuiltInRoles, r) {
        includeRoles = slices.DeleteFunc(includeRoles, func(x string) bool { return x == r })
    }
}

Prevention

When it happens

Trigger: Calling the backup API with includeRoles containing an exact built-in role name (e.g. 'admin', 'viewer' or any member of BuiltInRoles). Checked before wildcard expansion, so even alongside valid custom roles the request fails.

Common situations: Operator assumes all roles (including built-ins) must be listed for a full RBAC snapshot; scripts that copy every role from a role listing (which includes built-ins) into includeRoles; migration from setups where built-ins were regular roles.

Related errors


AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04). Data as JSON: /api/errors/8e697e6ee1a23e65. Report an issue: GitHub.