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
- 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.
- Validate every deny_rules entry with the same checks as allow_rules (non-empty name, valid headers/paths).
- 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
- Validate deny_rules with the same checks as allow_rules (name + valid request).
- deny_rules is optional; if present, every entry is fully validated.
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)