{"record":{"id":"20c3852e525085ca","repo":"vitessio/vitess","slug":"failed-to-execute-vtgate-fqdn-template-for-v-w","errorCode":null,"errorMessage":"failed to execute vtgate fqdn template for %v: %w","messagePattern":"failed to execute vtgate fqdn template for (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/cluster/discovery/discovery_consul.go","lineNumber":319,"sourceCode":"\t\t\tcase c.vtgateCellTag:\n\t\t\t\tcell = value\n\t\t\tcase c.vtgatePoolTag:\n\t\t\t\tpool = value\n\t\t\t}\n\t\t}\n\n\t\tvtgate.Cell = cell\n\t\tvtgate.Pool = pool\n\n\t\tif keyspaces, ok := entry.Service.Meta[c.vtgateKeyspacesToWatchTag]; ok {\n\t\t\tvtgate.Keyspaces = strings.Split(keyspaces, \",\")\n\t\t}\n\n\t\tif executeFQDNTemplate {\n\t\t\tif c.vtgateFQDNTmpl != nil {\n\t\t\t\tvtgate.FQDN, err = textutil.ExecuteTemplate(c.vtgateFQDNTmpl, vtgate)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"failed to execute vtgate fqdn template for %v: %w\", vtgate, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvtgates[i] = vtgate\n\t}\n\n\treturn vtgates, nil\n}\n\n// DiscoverVtctld is part of the Discovery interface.\nfunc (c *ConsulDiscovery) DiscoverVtctld(ctx context.Context, tags []string) (*vtadminpb.Vtctld, error) {\n\tspan, ctx := trace.NewSpan(ctx, \"ConsulDiscovery.DiscoverVtctld\")\n\tdefer span.Finish()\n\n\texecuteFQDNTemplate := true\n\n\treturn c.discoverVtctld(ctx, tags, executeFQDNTemplate)","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/cluster/discovery/discovery_consul.go#L301-L337","documentation":"discoverVTGates sets each vtgate's FQDN by executing c.vtgateFQDNTmpl against the vtgate when executeFQDNTemplate is enabled and the template is non-nil. If textutil.ExecuteTemplate fails, the whole discovery returns this wrapped error. It is raised once per vtgate inside the loop, so the message names the specific vtgate whose FQDN could not be rendered.","triggerScenarios":"Calling DiscoverVTGates / DiscoverVTGateAddrs / discoverVTGate on a consul cluster configured with vtgate_fqdn_template containing invalid syntax or field references not present on vtadminpb.VTGate.","commonSituations":"FQDN template like \"{{.Name}}.svc.cluster.local\" where the field is actually FQDN/Hostname on the proto; template syntax typo (unclosed {{ ); upgrade changed proto field names.","solutions":["Fix the vtgate fqdn template to reference only fields that exist on vtadminpb.VTGate","Validate the template compiles and executes with template.Must plus a sample struct in a scratch program","If FQDN templating is not needed, remove the fqdn template from the cluster config"],"exampleFix":"// before\nvtgate_fqdn_template: \"{{.Service}}.{{.Namespace}}.svc\"\n// after\nvtgate_fqdn_template: \"{{.Name}}.svc.cluster.local\"","handlingStrategy":"validation","validationCode":"if cfg.VtgateFQDNTmpl != \"\" {\n\tfqdnTmpl := template.Must(template.New(\"vtgate-fqdn\").Parse(cfg.VtgateFQDNTmpl))\n\tvar sample vtadminpb.VTGate\n\tif err := fqdnTmpl.Execute(io.Discard, &sample); err != nil {\n\t\treturn fmt.Errorf(\"invalid vtgate fqdn template: %w\", err)\n\t}\n}","typeGuard":null,"tryCatchPattern":"gates, err := cluster.DiscoverVTGates(ctx)\nif err != nil {\n\tif strings.Contains(err.Error(), \"fqdn template\") {\n\t\tlog.Errorf(\"bad vtgate fqdn template: %v\", err)\n\t\treturn nil, err\n\t}\n\treturn nil, err\n}","preventionTips":["Only reference fields actually present on vtadminpb.VTGate in fqdn templates","Drop the fqdn template from config when not required","Smoke-test the fqdn output with a single-gate discovery before full rollout","Re-validate templates after any Vitess proto change"],"tags":["go","vtadmin","consul","template","fqdn"],"backgroundTag":"template-execution-failed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}