{"record":{"id":"421b952590e49e7e","repo":"grpc/grpc-go","slug":"d-v","errorCode":null,"errorMessage":"%d: %v","messagePattern":"%d: %v","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"authz/rbac_translator.go","lineNumber":278,"sourceCode":"\tif len(and) > 0 {\n\t\treturn permissionAnd(and), nil\n\t}\n\treturn &v3rbacpb.Permission{\n\t\tRule: &v3rbacpb.Permission_Any{\n\t\t\tAny: true,\n\t\t},\n\t}, nil\n}\n\nfunc parseRules(rules []rule, prefixName string) (map[string]*v3rbacpb.Policy, error) {\n\tpolicies := make(map[string]*v3rbacpb.Policy)\n\tfor i, rule := range rules {\n\t\tif rule.Name == \"\" {\n\t\t\treturn policies, fmt.Errorf(`%d: \"name\" is not present`, i)\n\t\t}\n\t\tpermission, err := parseRequest(rule.Request)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%d: %v\", i, err)\n\t\t}\n\t\tpolicyName := prefixName + \"_\" + rule.Name\n\t\tpolicies[policyName] = &v3rbacpb.Policy{\n\t\t\tPrincipals:  []*v3rbacpb.Principal{parsePeer(rule.Source)},\n\t\t\tPermissions: []*v3rbacpb.Permission{permission},\n\t\t}\n\t}\n\treturn policies, nil\n}\n\n// Parse auditLoggingOptions to the associated RBAC protos. The single\n// auditLoggingOptions results in two different parsed protos, one for the allow\n// policy and one for the deny policy\nfunc (options *auditLoggingOptions) toProtos() (allow *v3rbacpb.RBAC_AuditLoggingOptions, deny *v3rbacpb.RBAC_AuditLoggingOptions, err error) {\n\tallow = &v3rbacpb.RBAC_AuditLoggingOptions{}\n\tdeny = &v3rbacpb.RBAC_AuditLoggingOptions{}\n\n\tif options.AuditCondition != \"\" {","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/authz/rbac_translator.go#L260-L296","documentation":"Returned by parseRules (rbac_translator.go:278) wrapping a failure from parseRequest(rule.Request) for the rule at index i. parseRequest in turn calls parseHeaders/parsePaths, so this aggregates the header/path validation errors with the rule index prefix. The '%v' carries the concrete sub-error (e.g. a 'headers N: key is not present' message).","triggerScenarios":"A rule in allow_rules/deny_rules whose request block contains an invalid path/header definition; the wrapped error pinpoints the field.","commonSituations":"Composite policy errors where the rule name is fine but its request matchers are malformed.","solutions":["Read the wrapped error (the %v) to find the concrete cause (e.g. missing header key/values), then fix that field in the rule at the reported index.","Validate each rule's request.headers and request.paths against the parser's rules (non-empty key, non-empty values, allowed header names) before deploying.","Reload via the file watcher so a malformed edit keeps the prior good policy while you correct it."],"exampleFix":"// before\n\"allow_rules\": [\n  { \"name\": \"r1\", \"request\": { \"headers\": [ {\"values\":[\"x\"]} ] } }\n]\n// error: 0: \"headers\" 0: \"key\" is not present\n\n// after\n\"allow_rules\": [\n  { \"name\": \"r1\", \"request\": { \"headers\": [ {\"key\":\"authorization\",\"values\":[\"x\"]} ] } }\n]","handlingStrategy":"validation","validationCode":"// Validate a full rule (name + request) before writing it into the policy.\nfunc validRule(r rule) error {\n    if r.Name == \"\" {\n        return errors.New(\"rule name required\")\n    }\n    for i, h := range r.Request.Headers {\n        if h.Key == \"\" {\n            return fmt.Errorf(\"headers %d: key required\", i)\n        }\n        if len(h.Values) == 0 {\n            return fmt.Errorf(\"headers %d: values required\", i)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"interceptor, err := authz.NewStatic(policyJSON)\nif err != nil {\n    // err is like: 2: \"headers\" 0: \"values\" is not present\n    // index 2 = the rule; inner message = the field to fix\n}","preventionTips":["Validate each rule's request.headers and request.paths before deploying.","Parse the composite error: leading index is the rule, remainder is the field cause.","Use file-watcher reload to keep serving the previous good policy."],"tags":["grpc","authz","rbac","policy","config","go"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}