{"record":{"id":"4fb537e07a908bc5","repo":"grpc/grpc-go","slug":"failed-to-start-resolver-w","errorCode":null,"errorMessage":"failed to start resolver: %w","messagePattern":"failed to start resolver: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clientconn.go","lineNumber":416,"sourceCode":"\tcc.mu.Unlock()\n\n\t// Set state to CONNECTING before building the name resolver\n\t// so the channel does not remain in IDLE.\n\tcc.csMgr.updateState(connectivity.Connecting)\n\n\t// This needs to be called without cc.mu because this builds a new resolver\n\t// which might update state or report error inline, which would then need to\n\t// acquire cc.mu.\n\tif err := cc.resolverWrapper.start(); err != nil {\n\t\t// If resolver creation fails, treat it like an error reported by the\n\t\t// resolver before any valid updates. Set channel's state to\n\t\t// TransientFailure, and set an erroring picker with the resolver build\n\t\t// error, which will returned as part of any subsequent RPCs.\n\t\tlogger.Warningf(\"Failed to start resolver: %v\", err)\n\t\tcc.csMgr.updateState(connectivity.TransientFailure)\n\t\tcc.mu.Lock()\n\t\tcc.updateResolverStateAndUnlock(resolver.State{}, err)\n\t\treturn fmt.Errorf(\"failed to start resolver: %w\", err)\n\t}\n\n\tcc.addTraceEvent(\"exiting idle mode\")\n\treturn nil\n}\n\n// initIdleStateLocked initializes common state to how it should be while idle.\nfunc (cc *ClientConn) initIdleStateLocked() {\n\tcc.resolverWrapper = newCCResolverWrapper(cc)\n\tcc.balancerWrapper = newCCBalancerWrapper(cc)\n\tcc.firstResolveEvent = grpcsync.NewEvent()\n\t// cc.conns == nil is a proxy for the ClientConn being closed. So, instead\n\t// of setting it to nil here, we recreate the map. This also means that we\n\t// don't have to do this when exiting idle mode.\n\tcc.conns = make(map[*addrConn]struct{})\n}\n\n// enterIdleMode puts the channel in idle mode, and as part of it shuts down the","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/clientconn.go#L398-L434","documentation":"Inside exitIdleMode (clientconn.go:407-417), the channel calls resolverWrapper.start(). If starting the resolver fails, the channel is moved to TransientFailure with an erroring picker and the build error is wrapped as \"failed to start resolver\". Any subsequent RPC, or the Dial/DialContext that triggered exit, gets this error.","triggerScenarios":"The resolver builder's Build() returns an error when the channel leaves idle mode — e.g. a custom resolver failing, or no builder registered for the target's scheme. Triggered on first RPC (NewClient) or immediately (Dial/DialContext).","commonSituations":"Target uses a scheme with no registered resolver; a custom resolver builder panics/errors; the resolver plugin isn't imported (blank import missing) so its init() never registers.","solutions":["Check the inner %w error for the resolver's Build failure message and fix that (register the builder, fix target scheme).","Add the missing blank import for the resolver package (e.g. _ \"google.golang.org/grpc/xds/googledirectpath\") if it self-registers in init().","Validate the target URL scheme before dialing."],"exampleFix":"// before\nconn, _ := grpc.NewClient(\"dns_nonexistent:///svc\")\n// after\nimport _ \"google.golang.org/grpc/internal/resolver/dns\"\nconn, _ := grpc.NewClient(\"dns:///svc:443\")","handlingStrategy":"validation","validationCode":"// Ensure a builder exists for the scheme (or default scheme) before dial.\nfunc ensureResolver(scheme string) error {\n    for _, s := range resolver.GetSchemes() { if s == scheme { return nil } }\n    return fmt.Errorf(\"no resolver registered for scheme %q\", scheme)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Import resolver packages so their init() registers builders before main dials.","Validate target scheme and default scheme at startup.","In custom resolvers, make Build() return descriptive errors."],"tags":["go","grpc","resolver","clientconn","idle"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}