{"record":{"id":"0f8b1d6dad864a15","repo":"grpc/grpc-go","slug":"xds-failed-to-create-a-new-channel-for-server-con","errorCode":null,"errorMessage":"xds: failed to create a new channel for server config %v: %v","messagePattern":"xds: failed to create a new channel for server config (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/clients/xdsclient/xdsclient.go","lineNumber":308,"sourceCode":"\tif err != nil {\n\t\treturn nil, func() {}, fmt.Errorf(\"xds: failed to create transport for server config %v: %v\", serverConfig, err)\n\t}\n\tstate := &channelState{\n\t\tparent:                c,\n\t\tserverConfig:          serverConfig,\n\t\tinterestedAuthorities: make(map[*authority]bool),\n\t}\n\tchannel, err := newXDSChannel(xdsChannelOpts{\n\t\ttransport:          tr,\n\t\tserverConfig:       serverConfig,\n\t\tclientConfig:       c.config,\n\t\teventHandler:       state,\n\t\tbackoff:            c.backoff,\n\t\twatchExpiryTimeout: c.watchExpiryTimeout,\n\t\tlogPrefix:          clientPrefix(c),\n\t})\n\tif err != nil {\n\t\treturn nil, func() {}, fmt.Errorf(\"xds: failed to create a new channel for server config %v: %v\", serverConfig, err)\n\t}\n\tstate.channel = channel\n\tc.xdsActiveChannels[*serverConfig] = state\n\tinitLocked(state)\n\treturn state.channel, c.releaseChannel(serverConfig, state, deInitLocked), nil\n}\n\n// releaseChannel is a function that is called when a reference to an xdsChannel\n// needs to be released. It handles closing channels with no active references.\n//\n// The function takes the following parameters:\n// - serverConfig: the server configuration for the xdsChannel\n// - state: the state of the xdsChannel\n// - deInitLocked: a function that performs any necessary cleanup for the xdsChannel\n//\n// The function returns another function that can be called to release the\n// reference to the xdsChannel. This returned function is idempotent, meaning\n// it can be called multiple times without any additional effect.","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/clients/xdsclient/xdsclient.go#L290-L326","documentation":"newXDSChannel returned an error when constructing the xdsChannel for a server config. newXDSChannel (channel.go:79-89) validates that transport, serverConfig, clientConfig, and eventHandler are all non-nil. This wraps that internal validation error, meaning one of the required channel components was nil at creation time.","triggerScenarios":"Called right after a transport is successfully built at xdsclient.go:289, but newXDSChannel at line 298 rejects one of the xdsChannelOpts fields as nil (channel.go:81-88). Since transport was just built and serverConfig/clientConfig come from the already-validated XDSClient, this is an internal invariant violation.","commonSituations":"A concurrent Close() racing with channel creation causing a field to become nil; a custom TransportBuilder returning (nil, nil) that bypasses the Build error check; internal gRPC bug in non-standard usage. Extremely rare in standard gRPC xDS client operation.","solutions":["If using a custom TransportBuilder, verify Build never returns (nil, nil)","Ensure the XDSClient is not used after Close() returns","If this occurs with unmodified gRPC, report it as a bug with a goroutine dump"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Wrap TransportBuilder to guard against nil-transport-with-nil-error returns.\ntype safeTransportBuilder struct{ inner clients.TransportBuilder }\nfunc (s safeTransportBuilder) Build(si clients.ServerIdentifier) (clients.Transport, error) {\n    t, err := s.inner.Build(si)\n    if err == nil && t == nil {\n        return nil, fmt.Errorf(\"TransportBuilder returned nil transport for %v\", si)\n    }\n    return t, err\n}\nconfig.TransportBuilder = safeTransportBuilder{inner: config.TransportBuilder}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not call xDS client methods after Close() returns","Wrap custom TransportBuilders with a nil-return guard to catch implementation bugs","Avoid concurrent Close() and resource watch operations on the same client instance"],"tags":["xds","internal","channel","invariant"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}