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
- Fix the datacenter template string so it parses as a valid Go text/template.
- Use only {{ .Cluster }} fields defined in vtadminpb.Cluster, e.g. "{{ .Cluster.Id }}-dc".
- Clear the datacenter template flag if the option is unused.
- 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
- Parse every datacenter template with text/template before wiring it into cluster config.
- Restrict templates to {{ .Cluster.* }} field paths from vtadminpb.Cluster.
- Store templates in lint-checked config files rather than ad-hoc shell strings.
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
- failed to execute template: %w
- failed to generate vtgate consul datacenter from template: %
- failed to parse vtgate FQDN template %s: %w
- failed to parse vtgate host address template %s: %w
- failed to generate vtctld consul datacenter from template: %
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/e39059d508bacfb3.
Report an issue: GitHub.