{"record":{"id":"31481c619bf4ee42","repo":"grpc/grpc-go","slug":"grpc-credentials-bundle-may-not-be-used-with-indi","errorCode":null,"errorMessage":"grpc: credentials.Bundle may not be used with individual TransportCredentials","messagePattern":"grpc: credentials\\.Bundle may not be used with individual TransportCredentials","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clientconn.go","lineNumber":93,"sourceCode":"\t// errConnIdling indicates the connection is being closed as the channel\n\t// is moving to an idle mode due to inactivity.\n\terrConnIdling = errors.New(\"grpc: the connection is closing due to channel idleness\")\n\t// invalidDefaultServiceConfigErrPrefix is used to prefix the json parsing error for the default\n\t// service config.\n\tinvalidDefaultServiceConfigErrPrefix = \"grpc: the provided default service config is invalid\"\n\t// PickFirstBalancerName is the name of the pick_first balancer.\n\tPickFirstBalancerName = pickfirst.Name\n)\n\n// The following errors are returned from Dial and DialContext\nvar (\n\t// errNoTransportSecurity indicates that there is no transport security\n\t// being set for ClientConn. Users should either set one or explicitly\n\t// call WithInsecure DialOption to disable security.\n\terrNoTransportSecurity = errors.New(\"grpc: no transport security set (use grpc.WithTransportCredentials(insecure.NewCredentials()) explicitly or set credentials)\")\n\t// errTransportCredsAndBundle indicates that creds bundle is used together\n\t// with other individual Transport Credentials.\n\terrTransportCredsAndBundle = errors.New(\"grpc: credentials.Bundle may not be used with individual TransportCredentials\")\n\t// errNoTransportCredsInBundle indicated that the configured creds bundle\n\t// returned a transport credentials which was nil.\n\terrNoTransportCredsInBundle = errors.New(\"grpc: credentials.Bundle must return non-nil transport credentials\")\n\t// errTransportCredentialsMissing indicates that users want to transmit\n\t// security information (e.g., OAuth2 token) which requires secure\n\t// connection on an insecure connection.\n\terrTransportCredentialsMissing = errors.New(\"grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)\")\n)\n\nvar (\n\tdisconnectionsMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{\n\t\tName:           \"grpc.subchannel.disconnections\",\n\t\tDescription:    \"EXPERIMENTAL. Number of times the selected subchannel becomes disconnected.\",\n\t\tUnit:           \"{disconnection}\",\n\t\tLabels:         []string{\"grpc.target\"},\n\t\tOptionalLabels: []string{\"grpc.lb.backend_service\", \"grpc.lb.locality\", \"grpc.disconnect_error\"},\n\t\tDefault:        false,\n\t})","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/clientconn.go#L75-L111","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before: control plane sends a raw custom proto\ntypedConfig:\n  \"@type\": type.googleapis.com/my.custom.AuditLog\n  fields: ...\n\n// after: wrap in TypedStruct so gRPC can extract JSON + name\ntypedConfig:\n  \"@type\": type.googleapis.com/xds.type.v3.TypedStruct\n  type_url: \"grpc.authz.audit_logging/mycustom\"\n  value:\n    fields: ...","handlingStrategy":"validation","validationCode":"// Verify the typed_config type_url is one of the supported types:\nfunc validateAuditTypedConfig(any *anypb.Any) error {\n    switch any.TypeUrl {\n    case \"type.googleapis.com/envoy.extensions.rbac.audit_loggers.stream.v3.StdoutAuditLog\",\n         \"type.googleapis.com/udpa.type.v1.TypedStruct\",\n         \"type.googleapis.com/xds.type.v3.TypedStruct\":\n        return nil\n    }\n    return fmt.Errorf(\"unsupported audit logger typed_config type: %s\", any.TypeUrl)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["xds","rbac","grpc","audit","proto","unsupported"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}