grpc/grpc-go · error

"deny_rules

Error message

"deny_rules" %v

What it means

Returned by translatePolicy (rbac_translator.go:383) wrapping a failure from parseRules(policy.DenyRules, policy.Name). It carries the index and sub-error of the first invalid deny rule (same rule format as allow_rules: each needs a name and a valid request block). The %v is the underlying parseRules error such as a missing rule name or bad header matcher.

Solutions

  1. Read the wrapped %v to find the offending deny rule and its sub-cause (e.g. '0: "name" is not present'), then fix that entry.
  2. Validate every deny_rules entry with the same checks as allow_rules (non-empty name, valid headers/paths).
  3. Use file-watcher reload so the previous policy stays active while you correct the file.

Example fix

// before
"deny_rules": [ { "request": { "paths": ["/admin"] } } ]
// error: "deny_rules" 0: "name" is not present

// after
"deny_rules": [ { "name": "block_admin", "request": { "paths": ["/admin"] } } ]
Defensive patterns

Strategy: validation

Validate before calling

for i, r := range denyRules {
    if r.Name == "" || !validRequest(r.Request) {
        return fmt.Errorf("deny_rules[%d]: invalid", i)
    }
}

Try / catch

interceptor, err := authz.NewStatic(policyJSON)
if err != nil {
    if strings.Contains(err.Error(), `"deny_rules"`) {
        // wrapped %v names the deny-rule index + cause; fix and reload
    }
}

Prevention

When it happens

Trigger: A deny_rules[] entry missing "name", or whose request.headers/paths are malformed; deny_rules is optional but if present each entry is fully validated.

Common situations: Adding deny rules modeled after allow rules but omitting required sub-fields; copy-paste errors.

Related errors


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

Appendix: source

Thrown at authz/rbac_translator.go:383

	d.DisallowUnknownFields()
	if err := d.Decode(policy); err != nil {
		return nil, "", fmt.Errorf("failed to unmarshal policy: %v", err)
	}
	if policy.Name == "" {
		return nil, "", fmt.Errorf(`"name" is not present`)
	}
	if len(policy.AllowRules) == 0 {
		return nil, "", fmt.Errorf(`"allow_rules" is not present`)
	}
	allowLogger, denyLogger, err := policy.AuditLoggingOptions.toProtos()
	if err != nil {
		return nil, "", err
	}
	rbacs := make([]*v3rbacpb.RBAC, 0, 2)
	if len(policy.DenyRules) > 0 {
		denyPolicies, err := parseRules(policy.DenyRules, policy.Name)
		if err != nil {
			return nil, "", fmt.Errorf(`"deny_rules" %v`, err)
		}
		denyRBAC := &v3rbacpb.RBAC{
			Action:              v3rbacpb.RBAC_DENY,
			Policies:            denyPolicies,
			AuditLoggingOptions: denyLogger,
		}
		rbacs = append(rbacs, denyRBAC)
	}
	allowPolicies, err := parseRules(policy.AllowRules, policy.Name)
	if err != nil {
		return nil, "", fmt.Errorf(`"allow_rules" %v`, err)
	}
	allowRBAC := &v3rbacpb.RBAC{Action: v3rbacpb.RBAC_ALLOW, Policies: allowPolicies, AuditLoggingOptions: allowLogger}
	return append(rbacs, allowRBAC), policy.Name, nil
}

View on GitHub (pinned to 0c51461d27)