vitessio/vitess · error

error parsing template %s: %w

Error message

error parsing template %s: %w

What it means

generateConsulDatacenter compiles the given datacenter template string with template.New(...).Parse. If parsing fails, this error wraps the raw template string and the parse error; it is propagated up to NewConsul for both the vtgate and vtctld datacenter options. It indicates the template string is syntactically invalid as a Go text/template.

Source

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

	if *vtctldFQDNTmplStr != "" {
		disco.vtctldFQDNTmpl, err = template.New("consul-vtctld-fqdn-template-" + cluster.Id).Parse(*vtctldFQDNTmplStr)
		if err != nil {
			return nil, fmt.Errorf("failed to parse vtctld FQDN template %s: %w", *vtctldFQDNTmplStr, err)
		}
	}

	disco.vtctldAddrTmpl, err = template.New("consul-vtctld-address-template-" + cluster.Id).Parse(*vtctldAddrTmplStr)
	if err != nil {
		return nil, fmt.Errorf("failed to parse vtctld host address template %s: %w", *vtctldAddrTmplStr, err)
	}

	return disco, nil
}

func generateConsulDatacenter(component string, cluster *vtadminpb.Cluster, tmplStr string) (string, error) {
	tmpl, err := template.New("consul-" + component + "-datacenter-" + cluster.Id).Parse(tmplStr)
	if err != nil {
		return "", fmt.Errorf("error parsing template %s: %w", tmplStr, err)
	}

	dc, err := textutil.ExecuteTemplate(tmpl, &struct {
		Cluster *vtadminpb.Cluster
	}{
		Cluster: cluster,
	})
	if err != nil {
		return "", fmt.Errorf("failed to execute template: %w", err)
	}

	return dc, nil
}

// DiscoverVTGate is part of the Discovery interface.
func (c *ConsulDiscovery) DiscoverVTGate(ctx context.Context, tags []string) (*vtadminpb.VTGate, error) {
	span, ctx := trace.NewSpan(ctx, "ConsulDiscovery.DiscoverVTGate")
	defer span.Finish()

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Fix the datacenter template string so it parses as a valid Go text/template.
  2. Use only {{ .Cluster }} fields defined in vtadminpb.Cluster, e.g. "{{ .Cluster.Id }}-dc".
  3. Clear the datacenter template flag if the option is unused.
  4. Test template strings locally with text/template's Parse before setting them in config.

Example fix

// before
--vtgate-datacenter-template="{{ .Cluster.Id "
// after
--vtgate-datacenter-template="{{ .Cluster.Id }}"
Defensive patterns

Strategy: validation

Validate before calling

func validateDCTemplate(component, tmplStr string) error {
    _, err := template.New("dc-check").Parse(tmplStr)
    return err
}

Try / catch

disco, err := NewConsul(cluster, args)
if err != nil && strings.Contains(err.Error(), "error parsing template") {
    log.Fatalf("invalid datacenter template: %v", err)
}

Prevention

When it happens

Trigger: Any NewConsul call with a non-empty vtgate- or vtctld-datacenter-template whose text/template syntax is invalid — unclosed actions, invalid field selectors, or unknown template functions.

Common situations: Config generated by templating tools leaving stray braces, hand-written templates with typos, docs examples truncated during copy-paste.

Related errors


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