grpc/grpc-go · error

: "name" is not present

Error message

%d: "name" is not present

What it means

Returned by parseRules (rbac_translator.go:274) when iterating allow_rules / deny_rules and a rule has an empty Name field. Each rule must have a name because it becomes the RBAC policy key (prefixed with the policy name at line 280); an empty name would collide and is rejected at the zero-based index i.

Solutions

  1. Add a unique, non-empty "name" to the rule at the reported index.
  2. Lint the policy so every rule in allow_rules/deny_rules has a non-empty name and names are unique within their list.

Example fix

// before
"allow_rules": [ { "request": { "paths": ["/foo"] } } ]

// after
"allow_rules": [ { "name": "allow_foo", "request": { "paths": ["/foo"] } } ]
Defensive patterns

Strategy: validation

Validate before calling

func validRule(r struct{ Name string }) error {
    if strings.TrimSpace(r.Name) == "" {
        return errors.New("rule name required")
    }
    return nil
}

Try / catch

interceptor, err := authz.NewStatic(policyJSON)
if err != nil {
    if strings.Contains(err.Error(), `"name" is not present`) {
        // the offending rule lacks a name; add one
    }
}

Prevention

When it happens

Trigger: An allow_rules[] or deny_rules[] entry missing "name" or with "name":"" in the policy JSON.

Common situations: Hand-authored policy; templated rules that omit name; refactoring that renamed fields.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/9c7180e52cf3a160. Report an issue: GitHub.

Appendix: source

Thrown at authz/rbac_translator.go:274

			return nil, err
		}
		and = append(and, permissionAnd(headers))
	}
	if len(and) > 0 {
		return permissionAnd(and), nil
	}
	return &v3rbacpb.Permission{
		Rule: &v3rbacpb.Permission_Any{
			Any: true,
		},
	}, nil
}

func parseRules(rules []rule, prefixName string) (map[string]*v3rbacpb.Policy, error) {
	policies := make(map[string]*v3rbacpb.Policy)
	for i, rule := range rules {
		if rule.Name == "" {
			return policies, fmt.Errorf(`%d: "name" is not present`, i)
		}
		permission, err := parseRequest(rule.Request)
		if err != nil {
			return nil, fmt.Errorf("%d: %v", i, err)
		}
		policyName := prefixName + "_" + rule.Name
		policies[policyName] = &v3rbacpb.Policy{
			Principals:  []*v3rbacpb.Principal{parsePeer(rule.Source)},
			Permissions: []*v3rbacpb.Permission{permission},
		}
	}
	return policies, nil
}

// Parse auditLoggingOptions to the associated RBAC protos. The single
// auditLoggingOptions results in two different parsed protos, one for the allow
// policy and one for the deny policy
func (options *auditLoggingOptions) toProtos() (allow *v3rbacpb.RBAC_AuditLoggingOptions, deny *v3rbacpb.RBAC_AuditLoggingOptions, err error) {

View on GitHub (pinned to 0c51461d27)