{"record":{"id":"2629d040aadf4688","repo":"grpc/grpc-go","slug":"deny-rules-v","errorCode":null,"errorMessage":"\"deny_rules\" %v","messagePattern":"\"deny_rules\" (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"authz/rbac_translator.go","lineNumber":383,"sourceCode":"\td.DisallowUnknownFields()\n\tif err := d.Decode(policy); err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"failed to unmarshal policy: %v\", err)\n\t}\n\tif policy.Name == \"\" {\n\t\treturn nil, \"\", fmt.Errorf(`\"name\" is not present`)\n\t}\n\tif len(policy.AllowRules) == 0 {\n\t\treturn nil, \"\", fmt.Errorf(`\"allow_rules\" is not present`)\n\t}\n\tallowLogger, denyLogger, err := policy.AuditLoggingOptions.toProtos()\n\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":365,"sourceCodeEnd":399,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/authz/rbac_translator.go#L365-L399","documentation":"Raised by translatePolicy when parseRules fails on the deny_rules array; the wrapped %v is the underlying parseRules error (typically error 82 or 83, i.e. a missing rule name or a bad request block inside a deny rule). It is prefixed with \"deny_rules\" so you know which array is at fault.","triggerScenarios":"The policy has deny_rules and one of its entries fails parseRules (no name, or a malformed request). translatePolicy wraps and re-throws the parseRules error.","commonSituations":"Adding deny rules by copying allow rules and forgetting to set the name; introducing a header/path matcher typo specifically in a deny rule; refactoring rules and leaving a deny entry incomplete.","solutions":["Read the wrapped %v — it contains the rule index and the specific sub-error (name missing vs request invalid).","Fix the flagged deny_rules entry (add name, fix request block).","Mirror the same validation you apply to allow_rules onto deny_rules in a unit test.","If the deny rule is no longer needed, remove it rather than leaving a half-edited entry."],"exampleFix":"// before:\n\"deny_rules\": [ { \"source\": { \"principals\": [\"bad\"] } } ]   // missing \"name\" -> parseRules error\n\n// after:\n\"deny_rules\": [ { \"name\": \"deny-bad\", \"source\": { \"principals\": [\"bad\"] } } ]","handlingStrategy":"validation","validationCode":"// Reuse validateRuleNames/validateRuleRequests scoped to deny_rules.\nfunc validateDenyRules(policyStr string) error {\n    var p struct {\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.DenyRules {\n        if r.Name == \"\" {\n            return fmt.Errorf(`\"deny_rules\"[%d]: \"name\" is not present`, i)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Apply the same name/request validation to deny_rules as to allow_rules.","Remove half-edited deny entries instead of leaving them.","Unit-test deny rules through the translator.","Lint deny rule names for uniqueness."],"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"}