grpc/grpc-go · error

failed to parse AuditCondition

Error message

failed to parse AuditCondition %v. Allowed values {NONE, ON_DENY, ON_ALLOW, ON_DENY_AND_ALLOW}

What it means

Returned by auditLoggingOptions.toProtos (rbac_translator.go:299) when audit_logging_options.audit_condition is non-empty but not one of the recognized enum strings. The parser looks up the value in the RBAC_AuditLoggingOptions_AuditCondition_value map; an unknown string yields this error listing the allowed set {NONE, ON_DENY, ON_ALLOW, ON_DENY_AND_ALLOW}.

Solutions

  1. Set audit_condition to one of the exact uppercase values: "NONE", "ON_DENY", "ON_ALLOW", "ON_DENY_AND_ALLOW", or omit it (empty means NONE).
  2. Lint the policy so any audit_condition is validated against the allowed enum set.

Example fix

// before
"audit_logging_options": { "audit_condition": "on_deny" }

// after
"audit_logging_options": { "audit_condition": "ON_DENY" }
Defensive patterns

Strategy: validation

Validate before calling

var allowedAudit = map[string]bool{"": true, "NONE": true, "ON_DENY": true, "ON_ALLOW": true, "ON_DENY_AND_ALLOW": true}
func validAuditCondition(v string) bool { return allowedAudit[strings.ToUpper(v)] && v == strings.ToUpper(v) }

Try / catch

interceptor, err := authz.NewStatic(policyJSON)
if err != nil {
    if strings.Contains(err.Error(), "AuditCondition") {
        // set audit_condition to one of NONE/ON_DENY/ON_ALLOW/ON_DENY_AND_ALLOW
    }
}

Prevention

When it happens

Trigger: Policy JSON with audit_logging_options.audit_condition set to a misspelled or wrong-case value, e.g. "on_deny" (lowercase) or "Always".

Common situations: Case mismatch (enum values are uppercase); typo; copying from docs that used a different casing; stale value from an older spec.

Understand the failure class

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/3d1a2113372f3b34. Report an issue: GitHub.

Appendix: source

Thrown at authz/rbac_translator.go:299

		policies[policyName] = &v3rbacpb.Policy{
			Principals:  []*v3rbacpb.Principal{parsePeer(rule.Source)},
			Permissions: []*v3rbacpb.Permission{permission},
		}
	}
	return policies, nil
}

// Parse auditLoggingOptions to the associated RBAC protos. The single
// auditLoggingOptions results in two different parsed protos, one for the allow
// policy and one for the deny policy
func (options *auditLoggingOptions) toProtos() (allow *v3rbacpb.RBAC_AuditLoggingOptions, deny *v3rbacpb.RBAC_AuditLoggingOptions, err error) {
	allow = &v3rbacpb.RBAC_AuditLoggingOptions{}
	deny = &v3rbacpb.RBAC_AuditLoggingOptions{}

	if options.AuditCondition != "" {
		rbacCondition, ok := v3rbacpb.RBAC_AuditLoggingOptions_AuditCondition_value[options.AuditCondition]
		if !ok {
			return nil, nil, fmt.Errorf("failed to parse AuditCondition %v. Allowed values {NONE, ON_DENY, ON_ALLOW, ON_DENY_AND_ALLOW}", options.AuditCondition)
		}
		allow.AuditCondition = v3rbacpb.RBAC_AuditLoggingOptions_AuditCondition(rbacCondition)
		deny.AuditCondition = toDenyCondition(v3rbacpb.RBAC_AuditLoggingOptions_AuditCondition(rbacCondition))
	}

	for i, config := range options.AuditLoggers {
		if config.Name == "" {
			return nil, nil, fmt.Errorf("missing required field: name in audit_logging_options.audit_loggers[%v]", i)
		}
		if config.Config == nil {
			config.Config = &structpb.Struct{}
		}
		typedStruct := &v1xdsudpatypepb.TypedStruct{
			TypeUrl: typeURLPrefix + config.Name,
			Value:   config.Config,
		}
		customConfig, err := anypb.New(typedStruct)
		if err != nil {

View on GitHub (pinned to 0c51461d27)