vitessio/vitess · error
failed to execute template: %w
Error message
failed to execute template: %w
What it means
generateConsulDatacenter executes a successfully-parsed datacenter template against a struct containing the cluster proto via textutil.ExecuteTemplate. If execution fails (data mismatch, nil field access, invalid pipeline at render time), this error wraps the runtime failure. Unlike error 898 this is a template execution error, not a parse error.
Source
Thrown at go/vt/vtadmin/cluster/discovery/discovery_consul.go:179
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()
executeFQDNTemplate := true
return c.discoverVTGate(ctx, tags, executeFQDNTemplate)
}
// discoverVTGate calls discoverVTGates and then returns a random VTGate from
// the result. see discoverVTGates for further documentation.
func (c *ConsulDiscovery) discoverVTGate(ctx context.Context, tags []string, executeFQDNTemplate bool) (*vtadminpb.VTGate, error) {View on GitHub (pinned to 01a25a7d17)
Solutions
- Remove or guard field accesses that can be nil (wrap with {{ if .Cluster.SomeField }}...{{ end }}).
- Only use plain fields of vtadminpb.Cluster (Id, Names, etc.) rather than methods or deep pointer chains.
- Read the wrapped error, which names the exact template line where execution failed.
- Ensure the vtadminpb.Cluster passed to discovery.New is fully populated, not a zero-value proto.
Example fix
// before
--vtgate-datacenter-template="{{ .Cluster.ProxyTopology.Address }}" // panics if ProxyTopology nil
// after
--vtgate-datacenter-template="{{ .Cluster.Id }}" Defensive patterns
Strategy: validation
Validate before calling
// execute a dry-run render before NewConsul
tmpl, err := template.New("dry").Parse(tmplStr)
if err == nil {
var buf bytes.Buffer
err = tmpl.Execute(&buf, struct{ Cluster *vtadminpb.Cluster }{Cluster: cluster})
} Try / catch
disco, err := NewConsul(cluster, args)
if err != nil && strings.Contains(err.Error(), "failed to execute template") {
log.Fatalf("template renders invalid data: %v", err)
} Prevention
- Guard potentially-nil proto fields with {{ if }} blocks before accessing them.
- Ensure the vtadminpb.Cluster passed to discovery.New is fully populated.
- Prefer plain fields over method calls in templates; proto wrappers may not expose methods.
- Dry-run render templates with a sample Cluster in tests.
When it happens
Trigger: Calling NewConsul with a datacenter template that parses but fails during ExecuteTemplate — e.g. the template calls a method/field on a nil value or has a runtime-invalid pipeline given the vtadminpb.Cluster data.
Common situations: Templates guarded with {{ if }} on fields that are nil pointers in the Cluster proto, method calls not defined on proto types, cluster proto fields left unset in the request.
Related errors
- error parsing template %s: %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/100e3b5a949da1d7.
Report an issue: GitHub.