grpc/grpc-go · error
rbac: Policy.condition is present
Error message
rbac: Policy.condition is present
What it means
Returned by the RBAC HTTP filter's parseConfig (rbac.go:63-64) when any policy in the RBAC rules has its condition field set. Per gRFC A41, gRPC's RBAC engine does not implement CEL condition expressions on policies, so their presence is a hard validation failure that NACKs the xDS config. The loop iterates every policy and rejects on the first non-nil Condition.
Source
Thrown at internal/xds/httpfilter/rbac/rbac.go:64
httpfilter.FilterConfig
chainEngine *rbac.ChainEngine
}
func (builder) TypeURLs() []string {
return []string{
"type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC",
"type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBACPerRoute",
}
}
// Parsing is the same for the base config and the override config.
func parseConfig(rbacCfg *rpb.RBAC) (httpfilter.FilterConfig, error) {
// All the validation logic described in A41.
for _, policy := range rbacCfg.GetRules().GetPolicies() {
// "Policy.condition and Policy.checked_condition must cause a
// validation failure if present." - A41
if policy.Condition != nil {
return nil, errors.New("rbac: Policy.condition is present")
}
if policy.CheckedCondition != nil {
return nil, errors.New("rbac: policy.CheckedCondition is present")
}
// "It is also a validation failure if Permission or Principal has a
// header matcher for a grpc- prefixed header name or :scheme." - A41
for _, principal := range policy.Principals {
name := principal.GetHeader().GetName()
if name == ":scheme" || strings.HasPrefix(name, "grpc-") {
return nil, fmt.Errorf("rbac: principal header matcher for %v is :scheme or starts with grpc", name)
}
}
for _, permission := range policy.Permissions {
name := permission.GetHeader().GetName()
if name == ":scheme" || strings.HasPrefix(name, "grpc-") {
return nil, fmt.Errorf("rbac: permission header matcher for %v is :scheme or starts with grpc", name)
}View on GitHub (pinned to 03255a9237)
Solutions
- Remove the condition field from all RBAC policies in the xDS config; express the same logic via permissions/principals (header, source IP, path matchers) instead.
- If CEL logic is mandatory, enforce it outside gRPC RBAC (e.g. an Envoy sidecar or an application-level interceptor).
- Validate the RBAC proto before publishing: any policy with condition != nil should be rejected/folded into matchers.
Example fix
// before
// policies: { p1: { condition: { ...CEL... }, permissions: [...] } }
// after
// policies: { p1: { permissions: [...], principals: [...] } } // no condition Defensive patterns
Strategy: validation
Validate before calling
func rbacPoliciesHaveNoCondition(cfg *rpb.RBAC) error {
for _, p := range cfg.GetRules().GetPolicies() {
if p.GetCondition() != nil {
return fmt.Errorf("policy %q uses unsupported condition", p)
}
}
return nil
} Prevention
- Do not use CEL conditions in RBAC policies destined for gRPC.
- Add an xDS/RBAC pre-publish lint rejecting condition fields.
- Document that gRPC RBAC only supports permission/principal matchers (gRFC A41).
When it happens
Trigger: An xDS RBAC HTTP filter config (type URL envoy.extensions.filters.http.rbac.v3.RBAC) whose rules.policies[*].condition is populated. parseConfig walks each policy and returns this error immediately.
Common situations: Porting an Envoy RBAC config that uses CEL conditions into an xDS-served gRPC deployment; a control plane that copies full Envoy RBAC features without filtering gRPC-incompatible ones.
Related errors
- rbac: policy.CheckedCondition is present
- input StringMatcher proto is nil
- unknown header matcher type
- filter missing name field
- rbac: principal header matcher for %v is :scheme or starts w
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/51eb67bae2ad6a48.
Report an issue: GitHub.