vitessio/vitess · error

failed to execute vtctld fqdn template for %v: %w

Error message

failed to execute vtctld fqdn template for %v: %w

What it means

discoverVtctlds optionally sets each vtctld's FQDN by executing c.vtctldFQDNTmpl (when executeFQDNTemplate is set and the template is non-nil). A template execution error is wrapped and returned, failing the entire vtctld discovery call that produced it.

Source

Thrown at go/vt/vtadmin/cluster/discovery/discovery_consul.go:437

		return nil, err
	}

	vtctlds := make([]*vtadminpb.Vtctld, len(entries))

	for i, entry := range entries {
		vtctld := &vtadminpb.Vtctld{
			Cluster: &vtadminpb.Cluster{
				Id:   c.cluster.Id,
				Name: c.cluster.Name,
			},
			Hostname: entry.Node.Node,
		}

		if executeFQDNTemplate {
			if c.vtctldFQDNTmpl != nil {
				vtctld.FQDN, err = textutil.ExecuteTemplate(c.vtctldFQDNTmpl, vtctld)
				if err != nil {
					return nil, fmt.Errorf("failed to execute vtctld fqdn template for %v: %w", vtctld, err)
				}
			}
		}

		vtctlds[i] = vtctld
	}

	return vtctlds, nil
}

// getQueryOptions returns a shallow copy so we can swap in the vtgateDatacenter.
// If we were to set it directly, we'd need a mutex to guard against concurrent
// vtgate and (soon) vtctld queries.
func (c *ConsulDiscovery) getQueryOptions() consul.QueryOptions {
	if c.queryOptions == nil {
		return consul.QueryOptions{}
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Fix the vtctld fqdn template to use only vtctld proto fields
  2. Remove the fqdn template from config if FQDN rewriting is unnecessary
  3. Test the template against a sample vtctld struct before rollout

Example fix

// before
vtctld_fqdn_template: "{{.Node}}.{{.Datacenter}}.consul"
// after
vtctld_fqdn_template: "{{.Hostname}}.example.internal"
Defensive patterns

Strategy: validation

Validate before calling

if cfg.VtctldFQDNTmpl != "" {
	fqdnTmpl := template.Must(template.New("vtctld-fqdn").Parse(cfg.VtctldFQDNTmpl))
	var sample vtadminpb.Vtctld
	if err := fqdnTmpl.Execute(io.Discard, &sample); err != nil {
		return fmt.Errorf("invalid vtctld fqdn template: %w", err)
	}
}

Try / catch

vts, err := cluster.DiscoverVtctlds(ctx)
if err != nil {
	if strings.Contains(err.Error(), "fqdn template") {
		log.Errorf("bad vtctld fqdn template: %v", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling DiscoverVtctlds / DiscoverVtctldAddrs / discoverVtctld on a cluster with a vtctld fqdn template configured, where executing the template against a vtctld errors out.

Common situations: FQDN template referencing consul catalog fields that were never copied onto the vtctld proto; malformed {{...}} syntax; template written for vtgate reused for vtctld with different fields.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/cceb988559185bfc. Report an issue: GitHub.