weaviate/weaviate · error

AddNamedPolicy: %w

Error message

AddNamedPolicy: %w

What it means

Raised in Manager.upsertRolesPermissions when casbin's AddNamedPolicy fails to persist one of the role's permission policies (p, role, resource, verb, domain). The wrap keeps the underlying casbin/adapter error, usually a storage failure or a policy rule that violates the model (wrong number of fields / invalid values).

Source

Thrown at usecases/auth/authorization/rbac/manager.go:146

	usersOrGroupsList := make([]string, 0, len(usersOrGroups))
	for user := range usersOrGroups {
		usersOrGroupsList = append(usersOrGroupsList, user)
	}

	return usersOrGroupsList, nil
}

func (m *Manager) upsertRolesPermissions(roles map[string][]authorization.Policy) error {
	for roleName, policies := range roles {
		// assign role to internal user to make sure to catch empty roles
		// e.g. : g, user:wv_internal_empty, role:roleName
		if _, err := m.casbin.AddRoleForUser(conv.UserNameWithTypeFromId(conv.InternalPlaceHolder, authentication.AuthTypeDb), conv.PrefixRoleName(roleName)); err != nil {
			return fmt.Errorf("AddRoleForUser: %w", err)
		}
		for _, policy := range policies {
			if _, err := m.casbin.AddNamedPolicy("p", conv.PrefixRoleName(roleName), policy.Resource, policy.Verb, policy.Domain); err != nil {
				return fmt.Errorf("AddNamedPolicy: %w", err)
			}
		}
	}
	if err := m.casbin.SavePolicy(); err != nil {
		return fmt.Errorf("SavePolicy: %w", err)
	}
	if err := m.casbin.InvalidateCache(); err != nil {
		return fmt.Errorf("InvalidateCache: %w", err)
	}
	return nil
}

func (m *Manager) GetRoles(names ...string) (map[string][]authorization.Policy, error) {
	m.restoreLock.RLock()
	defer m.restoreLock.RUnlock()

	var (
		casbinStoragePolicies    [][][]string

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Unwrap the error and check the underlying cause: fix storage issues first (disk, file permissions, adapter health).
  2. Validate each policy (non-empty Resource, valid Verb, Domain) before calling Create/UpdateRolesPermissions.
  3. Serialize role updates (avoid concurrent CreateRolesPermissions/UpdateRolesPermissions on the same role) and retry transient failures.

Example fix

// before: empty resource in policy causes AddNamedPolicy failure
{"reader": [{"resource": "", "verb": "get", "domain": "*"}]}
// after: validate before submitting
for _, p := range policies {
    if p.Resource == "" || p.Verb == "" {
        return fmt.Errorf("invalid policy: %+v", p)
    }
}
Defensive patterns

Strategy: validation

Validate before calling

for _, p := range policies {
    if p.Resource == "" || p.Verb == "" || p.Domain == "" {
        return fmt.Errorf("invalid policy %+v: resource, verb and domain are required", p)
    }
}

Type guard

func validPolicy(p authorization.Policy) bool {
    return p.Resource != "" && p.Verb != "" && p.Domain != ""
}

Try / catch

err := manager.UpdateRolesPermissions(ctx, roles)
if err != nil {
    if strings.Contains(err.Error(), "AddNamedPolicy") {
        logger.Errorf("policy write rejected; verify policy fields and storage: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: CreateRolesPermissions or UpdateRolesPermissions passing a Policy whose Resource/Verb/Domain fields don't fit the casbin model (e.g. empty resource, extra segment) or where the policy adapter cannot write (file error, concurrent modification).

Common situations: Clients posting role definitions with empty or malformed resource paths; policy storage on a read-only filesystem; concurrent role updates causing the adapter to reject writes.

Related errors


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