{"record":{"id":"8b02a2de149f4444","repo":"grpc/grpc-go","slug":"allow-rules-v","errorCode":null,"errorMessage":"\"allow_rules\" %v","messagePattern":"\"allow_rules\" (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"authz/rbac_translator.go","lineNumber":394,"sourceCode":"\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\trbacs := make([]*v3rbacpb.RBAC, 0, 2)\n\tif len(policy.DenyRules) > 0 {\n\t\tdenyPolicies, err := parseRules(policy.DenyRules, policy.Name)\n\t\tif err != nil {\n\t\t\treturn nil, \"\", fmt.Errorf(`\"deny_rules\" %v`, err)\n\t\t}\n\t\tdenyRBAC := &v3rbacpb.RBAC{\n\t\t\tAction:              v3rbacpb.RBAC_DENY,\n\t\t\tPolicies:            denyPolicies,\n\t\t\tAuditLoggingOptions: denyLogger,\n\t\t}\n\t\trbacs = append(rbacs, denyRBAC)\n\t}\n\tallowPolicies, err := parseRules(policy.AllowRules, policy.Name)\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(`\"allow_rules\" %v`, err)\n\t}\n\tallowRBAC := &v3rbacpb.RBAC{Action: v3rbacpb.RBAC_ALLOW, Policies: allowPolicies, AuditLoggingOptions: allowLogger}\n\treturn append(rbacs, allowRBAC), policy.Name, nil\n}\n","sourceCodeStart":376,"sourceCodeEnd":399,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/authz/rbac_translator.go#L376-L399","documentation":"Raised by translatePolicy when parseRules fails on the (mandatory) allow_rules array; the wrapped %v is the underlying parseRules error (error 82 or 83). Because allow_rules is always parsed, this is the most common surface for a malformed rule — the prefix \"allow_rules\" disambiguates it from the deny variant (error 90).","triggerScenarios":"An allow_rules entry is missing its name, or its request block fails parseRequest/parsePaths/parseHeaders. translatePolicy wraps the parseRules error with the \"allow_rules\" prefix.","commonSituations":"Same shape as errors 82/83 but surfaced through the allow path: copy-pasted rule without a name, a typo in a path/header matcher, or a schema mismatch after an SDK upgrade.","solutions":["Read the wrapped %v for the rule index and specific sub-error.","Fix the named allow_rules entry (name field or request block).","Add a unit test parsing allow_rules through the translator to catch this pre-deploy.","Validate every allow rule has a unique name and a well-formed request."],"exampleFix":"// before:\n\"allow_rules\": [ { \"request\": { \"paths\": [\"/api\"] } } ]   // missing \"name\"\n\n// after:\n\"allow_rules\": [ { \"name\": \"allow-api\", \"request\": { \"paths\": [\"/api\"] } } ]","handlingStrategy":"validation","validationCode":"// Reuse validateRuleNames/validateRuleRequests scoped to allow_rules.\nfunc validateAllowRules(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    }\n    if err := json.Unmarshal([]byte(policyStr), &p); err != nil { return err }\n    for i, r := range p.AllowRules {\n        if r.Name == \"\" {\n            return fmt.Errorf(`\"allow_rules\"[%d]: \"name\" is not present`, i)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate allow rule names + request blocks before deploy.","Generate allow rules from typed structs to avoid typos.","CI-lint for unique, non-empty names.","Keep a golden-policy test that must keep parsing."],"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"}