grpc/grpc-go · error
grpc: credentials.Bundle may not be used with individual…
Error message
grpc: credentials.Bundle may not be used with individual TransportCredentials
What it means
Thrown by getCustomConfig when the TypedConfig's unwrapped proto message is not one of the three handled types: *v1xdsudpatypepb.TypedStruct, *v3xdsxdstypepb.TypedStruct, or *v3auditloggersstreampb.StdoutAuditLog. The Any's type_url pointed to a proto type that the RBAC audit converter has no conversion logic for, so it rejects the config with the type_url for diagnosis.
Solutions
- Wrap the custom audit logger configuration in a TypedStruct (udpa.type.v1.TypedStruct or xds.type.v3.TypedStruct) with the type_url set to grpc.authz.audit_logging/<LoggerName>, so the converter extracts the JSON and delegates to the registered factory.
- If the logger type is a standard Envoy extension not yet supported by grpc-go, upgrade grpc-go or file a feature request.
- Mark the audit logger config as optional (is_optional=true) to suppress the error and skip logging for unsupported types.
Example fix
// before: control plane sends a raw custom proto
typedConfig:
"@type": type.googleapis.com/my.custom.AuditLog
fields: ...
// after: wrap in TypedStruct so gRPC can extract JSON + name
typedConfig:
"@type": type.googleapis.com/xds.type.v3.TypedStruct
type_url: "grpc.authz.audit_logging/mycustom"
value:
fields: ... Defensive patterns
Strategy: validation
Validate before calling
// Verify the typed_config type_url is one of the supported types:
func validateAuditTypedConfig(any *anypb.Any) error {
switch any.TypeUrl {
case "type.googleapis.com/envoy.extensions.rbac.audit_loggers.stream.v3.StdoutAuditLog",
"type.googleapis.com/udpa.type.v1.TypedStruct",
"type.googleapis.com/xds.type.v3.TypedStruct":
return nil
}
return fmt.Errorf("unsupported audit logger typed_config type: %s", any.TypeUrl)
} Prevention
- Wrap custom audit logger configs in TypedStruct (xds.type.v3.TypedStruct) with the logger name in the type_url.
- Keep a list of supported audit logger type_urls and validate against it before constructing the engine.
- Set is_optional=true for unsupported logger types to allow graceful degradation.
When it happens
Trigger: The control plane sends an audit logger typed_config whose type_url resolves to a proto message not in the converter's switch — for example, a hypothetical envoy.extensions.rbac.audit_loggers.http.v3.HttpAuditLog or any custom audit logger proto that lacks a TypedStruct wrapper. The UnmarshalNew() succeeds (the proto is registered) but the type is unrecognized.
Common situations: A control plane that supports an audit logger type (e.g., a file-based or HTTP-based logger) that grpc-go's RBAC converter does not yet implement. A new Envoy audit logger extension sent before grpc-go adds support. A custom audit logger proto that is not wrapped in a TypedStruct (the mechanism gRPC uses for custom logger configs).
Related errors
- all SubConns are in TransientFailure
- ALTS: untrusted platform. ALTS is only supported on GCP
- bad resolver state
- client-side auth info is not of type alts.AuthInfo
- grpc: credentials.Bundle must return non-nil transport…
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/31481c619bf4ee42.
Report an issue: GitHub.
Appendix: source
Thrown at clientconn.go:93
// errConnIdling indicates the connection is being closed as the channel
// is moving to an idle mode due to inactivity.
errConnIdling = errors.New("grpc: the connection is closing due to channel idleness")
// invalidDefaultServiceConfigErrPrefix is used to prefix the json parsing error for the default
// service config.
invalidDefaultServiceConfigErrPrefix = "grpc: the provided default service config is invalid"
// PickFirstBalancerName is the name of the pick_first balancer.
PickFirstBalancerName = pickfirst.Name
)
// The following errors are returned from Dial and DialContext
var (
// errNoTransportSecurity indicates that there is no transport security
// being set for ClientConn. Users should either set one or explicitly
// call WithInsecure DialOption to disable security.
errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithTransportCredentials(insecure.NewCredentials()) explicitly or set credentials)")
// errTransportCredsAndBundle indicates that creds bundle is used together
// with other individual Transport Credentials.
errTransportCredsAndBundle = errors.New("grpc: credentials.Bundle may not be used with individual TransportCredentials")
// errNoTransportCredsInBundle indicated that the configured creds bundle
// returned a transport credentials which was nil.
errNoTransportCredsInBundle = errors.New("grpc: credentials.Bundle must return non-nil transport credentials")
// errTransportCredentialsMissing indicates that users want to transmit
// security information (e.g., OAuth2 token) which requires secure
// connection on an insecure connection.
errTransportCredentialsMissing = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)")
)
var (
disconnectionsMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
Name: "grpc.subchannel.disconnections",
Description: "EXPERIMENTAL. Number of times the selected subchannel becomes disconnected.",
Unit: "{disconnection}",
Labels: []string{"grpc.target"},
OptionalLabels: []string{"grpc.lb.backend_service", "grpc.lb.locality", "grpc.disconnect_error"},
Default: false,
})View on GitHub (pinned to 0c51461d27)