{"record":{"id":"30af6b923f1eab52","repo":"vitessio/vitess","slug":"s-unsupported-url-host-s","errorCode":null,"errorMessage":"%s: unsupported URL host %s","messagePattern":"(.+?): unsupported URL host (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/cluster/resolver/resolver.go","lineNumber":257,"sourceCode":"\t\treturn nil, err\n\t}\n\n\tb.m.Lock()\n\tb.resolvers = append(b.resolvers, r)\n\tb.m.Unlock()\n\n\treturn r, nil\n}\n\nfunc (b *builder) build(target grpcresolver.Target, cc grpcresolver.ClientConn, opts grpcresolver.BuildOptions) (*resolver, error) {\n\tvar fn func(context.Context, []string) ([]string, error)\n\tswitch target.URL.Host {\n\tcase \"vtctld\":\n\t\tfn = b.opts.Discovery.DiscoverVtctldAddrs\n\tcase \"vtgate\":\n\t\tfn = b.opts.Discovery.DiscoverVTGateAddrs\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"%s: unsupported URL host %s\", logPrefix, target.URL.Host)\n\t}\n\n\tvar sc serviceconfig.Config\n\tif b.opts.BalancerPolicy != \"\" {\n\t\t// c.f. https://github.com/grpc/grpc/blob/master/doc/service_config.md#example\n\t\tscpr := cc.ParseServiceConfig(fmt.Sprintf(`{\"loadBalancingConfig\": [{ \"%s\": {} }] }`, b.opts.BalancerPolicy))\n\t\tif scpr.Err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to initialize service config with load balancer policy %s: %s\", b.opts.BalancerPolicy, scpr.Err)\n\t\t}\n\n\t\tsc = scpr.Config\n\t}\n\n\tctx, cancel := context.WithCancel(context.Background())\n\n\tr := &resolver{\n\t\tcomponent: target.URL.Host,\n\t\t// use the original cluster ID (not the sanitized scheme) for debugging/logging","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/cluster/resolver/resolver.go#L239-L275","documentation":"The gRPC resolver builder (build) maps the target URL's host to a discovery function; only hosts \"vtctld\" and \"vtgate\" are supported. Any other host means the resolver has no way to discover backend addresses, so building the resolver fails with this error. The logPrefix identifies which resolver/cluster failed.","triggerScenarios":"Calling resolver.Build or mustBuild with a target like \"cluster://ks/other\" or a mistyped scheme URL whose URL.Host is not exactly 'vtctld' or 'vtgate' — e.g. \"cluster://vtctlds/...\" (plural) or a full hostname in the target.","commonSituations":"Constructing gRPC dial targets by hand with wrong pseudo-host names; templated configs where the component segment is interpolated with a typo; adding a new component type without updating the resolver switch.","solutions":["Set the target URL host to exactly 'vtctld' or 'vtgate' (e.g. cluster://mycluster/vtctld).","Check how the dial target string is constructed/templated for typos.","Verify scheme parsing: the host is whatever sits between the second '/' and the next '/'.","If a new component is required, extend build's switch with a discovery function (code change)."],"exampleFix":"// before\ncc, err := resolver.Build(target, ...) // target: \"cluster://vtctlds/account\"\n// after\ncc, err := resolver.Build(\"cluster://account/vtctld\", ...)","handlingStrategy":"validation","validationCode":"u, err := url.Parse(target)\nif err != nil { return err }\nif h := u.Host; h != \"vtctld\" && h != \"vtgate\" {\n  return fmt.Errorf(\"unsupported resolver host %q\", h)\n}","typeGuard":"func isSupportedResolverTarget(target string) bool {\n  u, err := url.Parse(target)\n  return err == nil && (u.Host == \"vtctld\" || u.Host == \"vtgate\")\n}","tryCatchPattern":"cc, err := resolver.Build(target, opts)\nif err != nil {\n  if strings.Contains(err.Error(), \"unsupported URL host\") {\n    log.Warn(\"bad dial target, falling back\", slog.String(\"target\", target))\n    return grpc.Dial(fallbackAddr)\n  }\n  return err\n}","preventionTips":["Centralize dial-target construction in one helper.","Use constants for component names instead of interpolated strings.","Unit-test target templates for every component type.","Remember the URL host must be the pseudo-host, not a real hostname."],"tags":["grpc","resolver","discovery","configuration"],"backgroundTag":"unsupported-target-host","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}