{"record":{"id":"6f67689f50896f17","repo":"grpc/grpc-go","slug":"rbac-error-constructing-matching-engine-v","errorCode":null,"errorMessage":"rbac: error constructing matching engine: %v","messagePattern":"rbac: error constructing matching engine: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/rbac/rbac.go","lineNumber":112,"sourceCode":"\n\t// Two cases where this HTTP Filter is a no op:\n\t// \"If absent, no enforcing RBAC policy will be applied\" - RBAC\n\t// Documentation for Rules field.\n\t// \"At this time, if the RBAC.action is Action.LOG then the policy will be\n\t// completely ignored, as if RBAC was not configured.\" - A41\n\tif rbacCfg.Rules == nil || rbacCfg.GetRules().GetAction() == v3rbacpb.RBAC_LOG {\n\t\treturn config{}, nil\n\t}\n\n\t// TODO(gregorycooke) - change the call chain to here so we have the filter\n\t// name to input here instead of an empty string. It will come from here:\n\t// https://github.com/grpc/grpc-go/blob/eff0942e95d93112921414aee758e619ec86f26f/xds/internal/xdsclient/xdsresource/unmarshal_lds.go#L199\n\tce, err := rbac.NewChainEngine([]*v3rbacpb.RBAC{rbacCfg.GetRules()}, \"\")\n\tif err != nil {\n\t\t// \"At this time, if the RBAC.action is Action.LOG then the policy will be\n\t\t// completely ignored, as if RBAC was not configured.\" - A41\n\t\tif rbacCfg.GetRules().GetAction() != v3rbacpb.RBAC_LOG {\n\t\t\treturn nil, fmt.Errorf(\"rbac: error constructing matching engine: %v\", err)\n\t\t}\n\t}\n\n\treturn config{chainEngine: ce}, nil\n}\n\n// normalizePermissionHeaders applies the A41 header-name rules to every header\n// matcher reachable from permission, including those nested inside and/or/not\n// rules.\nfunc normalizePermissionHeaders(permission *v3rbacpb.Permission) error {\n\tswitch p := permission.GetRule().(type) {\n\tcase *v3rbacpb.Permission_Header:\n\t\treturn normalizeHeaderMatcher(p.Header)\n\tcase *v3rbacpb.Permission_AndRules:\n\t\tfor _, rule := range p.AndRules.GetRules() {\n\t\t\tif err := normalizePermissionHeaders(rule); err != nil {\n\t\t\t\treturn err\n\t\t\t}","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/httpfilter/rbac/rbac.go#L94-L130","documentation":"parseConfig (rbac.go:112) wraps an error from rbac.NewChainEngine, which builds the policy-matching engine from the RBAC rules. Construction can fail on malformed permissions/principals, unsupported matcher types, or invalid regex/CEL-like expressions even after A41 header-name validation passes.","triggerScenarios":"An RBAC policy passes the A41 condition/header-name checks but contains a permission or principal that the chain engine cannot compile — e.g., an unknown permission/principal identifier kind, an invalid regex, or a malformed matcher.","commonSituations":"Control-plane emits a policy that uses a matcher grpc-go does not yet support (version skew); hand-authored RBAC config with a typo'd regex; partial upgrade of the rbac matcher library.","solutions":["Read the wrapped error from rbac.NewChainEngine to find the offending matcher or permission.","Simplify the policy (remove the offending permission/principal) to isolate the failing rule.","Align grpc-go and go-control-plane versions so the matcher library understands the policy shape."],"exampleFix":"// before: policy references an unsupported matcher\npermissions: [{ rule: { destination_port: { range: { start: 0, end: 0 } } } }]\n\n// after: use a supported permission kind\npermissions: [{ rule: { url_path: { path: { exact: \"/foo\" } } } }]","handlingStrategy":"validation","validationCode":"// Validate the policy compiles standalone before shipping it:\nce, err := rbac.NewChainEngine([]*v3rbacpb.RBAC{policy}, \"\")\nif err != nil {\n    return fmt.Errorf(\"policy does not compile: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"fc, err := rbacBuilder.ParseFilterConfig(anyCfg)\nif err != nil && strings.Contains(err.Error(), \"constructing matching engine\") {\n    // strip permissions/principals one by one to isolate the failing rule\n}","preventionTips":["Pre-compile RBAC policies in CI using rbac.NewChainEngine before publishing.","Keep grpc-go and go-control-plane versions aligned.","Avoid matcher types not yet supported by the data-plane's rbac library."],"tags":["rbac","config","policy","xds","grpc"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}