grpc/grpc-go · error

error parsing custom audit logger config

Error message

error parsing custom audit logger config: %v

What it means

Returned by auditLoggingOptions.toProtos (rbac_translator.go:318) when anypb.New(typedStruct) fails while packing the custom audit logger config into a protobuf Any. The TypedStruct wraps the logger's structpb.Struct config with a typeURL of 'grpc.authz.audit_logging/<name>'. anypb.New fails only when the message cannot be serialized (e.g. contains invalid UTF-8 strings in the Struct, or an internal proto error).

Solutions

  1. Ensure all string values in the audit logger config object are valid UTF-8.
  2. Simplify the config to isolate which field causes the marshal failure, then correct the offending value.
  3. If using a programmatically built structpb.Struct, validate strings before insertion.

Example fix

// before
"config": { "topic": "<invalid utf-8 bytes>" }

// after
"config": { "topic": "audit-events" }
Defensive patterns

Strategy: validation

Validate before calling

import "unicode/utf8"
func validStructStrings(s *structpb.Struct) error {
    if s == nil { return nil }
    for k, v := range s.Fields {
        if !utf8.ValidString(k) { return fmt.Errorf("invalid utf-8 key: %q", k) }
        if v.GetStringValue() != "" && !utf8.ValidString(v.GetStringValue()) {
            return fmt.Errorf("invalid utf-8 value for key %q", k)
        }
    }
    return nil
}

Try / catch

interceptor, err := authz.NewStatic(policyJSON)
if err != nil {
    if strings.Contains(err.Error(), "error parsing custom audit logger config") {
        // sanitize the audit logger config struct (valid UTF-8) and reload
    }
}

Prevention

When it happens

Trigger: An audit logger config Struct whose string values contain invalid UTF-8 bytes, or otherwise cannot be marshaled by proto; extremely rare in normal operation.

Common situations: Binary/non-UTF-8 data placed into a Struct string field; corrupt Struct construction; protobuf version mismatch producing a marshal error.

Related errors


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

Appendix: source

Thrown at authz/rbac_translator.go:318

		}
		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 {
			return nil, nil, fmt.Errorf("error parsing custom audit logger config: %v", err)
		}

		logger := &v3corepb.TypedExtensionConfig{Name: config.Name, TypedConfig: customConfig}
		rbacConfig := v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
			IsOptional:  config.IsOptional,
			AuditLogger: logger,
		}
		allow.LoggerConfigs = append(allow.LoggerConfigs, &rbacConfig)
		deny.LoggerConfigs = append(deny.LoggerConfigs, &rbacConfig)
	}

	return allow, deny, nil
}

// Maps the AuditCondition coming from AuditLoggingOptions to the proper
// condition for the deny policy RBAC proto
func toDenyCondition(condition v3rbacpb.RBAC_AuditLoggingOptions_AuditCondition) v3rbacpb.RBAC_AuditLoggingOptions_AuditCondition {
	// Mapping the overall policy AuditCondition to what it must be for the Deny and Allow RBAC

View on GitHub (pinned to 0c51461d27)