{"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/03255a9237b6eb32710f6bc4f2de9a675b99fe36/authz/rbac_translator.go#L260-L296","documentation":"Raised by parseRules when parseRequest(rule.Request) fails for rule at index %d; the wrapped %v is the underlying request-parsing error (e.g. malformed path/header matcher). The gRPC authz translator converts each rule's \"request\" block into an RBAC Permission, so any invalid field in that block surfaces here with its index.","triggerScenarios":"An allow_rules/deny_rules entry has a \"request\" object whose Paths or Headers fail validation inside parseRequest/parsePaths/parseHeaders. The error bubbles up wrapped as `index: underlying-error`.","commonSituations":"A header matcher with an invalid key or an unsupported matcher type; a path entry that is empty or fails the path-syntax check; a schema change in the SDK where a previously-tolerated field is now rejected; YAML-to-JSON conversion mangling nested header objects.","solutions":["Read the wrapped %v in the error message — it names the exact request sub-field that failed (path/header).","Go to the rule at the reported index and fix the flagged field (e.g. supply a valid header name, a non-empty path).","Add a unit test that parses the policy JSON through the same translator path to fail fast on invalid request blocks.","Diff the policy against the SDK's documented request schema for your gRPC version."],"exampleFix":"// before:\n{ \"name\": \"r0\", \"request\": { \"headers\": [ { \"key\": \"\", \"values\": [\"x\"] } ] } }  // empty header key -> parseHeaders fails\n\n// after:\n{ \"name\": \"r0\", \"request\": { \"headers\": [ { \"key\": \"x-custom\", \"values\": [\"allowed\"] } ] } }","handlingStrategy":"validation","validationCode":"// Pre-flight: round-trip each rule's request through the SDK structs to\n// surface request-block errors before serving the policy.\nfunc validateRuleRequests(policyStr string) error {\n    var p struct {\n        AllowRules []struct {\n            Name    string          `json:\"name\"`\n            Request json.RawMessage `json:\"request\"`\n        } `json:\"allow_rules\"`\n        DenyRules []struct {\n            Name    string          `json:\"name\"`\n            Request json.RawMessage `json:\"request\"`\n        } `json:\"deny_rules\"`\n    }\n    if err := json.Unmarshal([]byte(policyStr), &p); err != nil { return err }\n    for i, r := range p.AllowRules {\n        var req interface{} // replace with the SDK request struct\n        if err := json.Unmarshal(r.Request, &req); err != nil {\n            return fmt.Errorf(\"allow_rules[%d]: %v\", i, err)\n        }\n    }\n    for i, r := range p.DenyRules {\n        var req interface{}\n        if err := json.Unmarshal(r.Request, &req); err != nil {\n            return fmt.Errorf(\"deny_rules[%d]: %v\", i, err)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate request blocks (paths, headers) for non-empty well-formed values.","Unit-test each rule against the SDK translator.","Document the supported header/path matcher shapes for your version.","Lint header keys are non-empty and lowercase-per gRPC metadata conventions."],"tags":["authz","rbac","authorization-policy","config","validation"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}