vitessio/vitess · error
failed to generate vtctld consul datacenter from template: %
Error message
failed to generate vtctld consul datacenter from template: %w
What it means
Analogous to the vtgate case, NewConsul renders the optional vtctld datacenter template via generateConsulDatacenter and wraps any parse/execute failure with this message. It signals that the vtctld datacenter template string is invalid or cannot be rendered against the cluster proto.
Source
Thrown at go/vt/vtadmin/cluster/discovery/discovery_consul.go:148
}
if *vtgateFQDNTmplStr != "" {
disco.vtgateFQDNTmpl, err = template.New("consul-vtgate-fqdn-template-" + cluster.Id).Parse(*vtgateFQDNTmplStr)
if err != nil {
return nil, fmt.Errorf("failed to parse vtgate FQDN template %s: %w", *vtgateFQDNTmplStr, err)
}
}
disco.vtgateAddrTmpl, err = template.New("consul-vtgate-address-template-" + cluster.Id).Parse(*vtgateAddrTmplStr)
if err != nil {
return nil, fmt.Errorf("failed to parse vtgate host address template %s: %w", *vtgateAddrTmplStr, err)
}
/* vtctld options */
if *vtctldDatacenterTmplStr != "" {
disco.vtctldDatacenter, err = generateConsulDatacenter("vtctld", cluster, *vtctldDatacenterTmplStr)
if err != nil {
return nil, fmt.Errorf("failed to generate vtctld consul datacenter from template: %w", err)
}
}
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
}
View on GitHub (pinned to 01a25a7d17)
Solutions
- Fix the vtctld datacenter template syntax to be a valid Go text/template.
- Reference only valid vtadminpb.Cluster fields (e.g. {{ .Cluster.Id }}).
- Leave the vtctld datacenter template empty to skip the feature — it is only parsed when non-empty.
- Read the wrapped inner error to distinguish parse vs execution failure.
Example fix
// before
--vtctld-datacenter-template="{{ if .Cluster.Id }}dc1"
// after
--vtctld-datacenter-template="{{ if .Cluster.Id }}dc1{{ end }}" Defensive patterns
Strategy: validation
Validate before calling
if s := *vtctldDatacenterTmplStr; s != "" {
if _, err := template.New("check").Parse(s); err != nil {
return fmt.Errorf("invalid vtctld dc template: %w", err)
}
} Try / catch
disco, err := NewConsul(cluster, args)
if err != nil && strings.Contains(err.Error(), "vtctld consul datacenter") {
log.Fatalf("bad vtctld datacenter template: %v", err)
} Prevention
- Mirror the vtgate template only after verifying its syntax.
- Guard nil fields with {{ if }} ... {{ end }} when rendering Cluster data.
- Validate all non-empty template flags at config load time.
When it happens
Trigger: Passing a non-empty vtctld-datacenter-template flag whose Go template fails to parse (syntax error) or whose execution against &struct{Cluster *vtadminpb.Cluster} fails, during NewConsul.
Common situations: Invalid template syntax from manual edits, referencing nonexistent Cluster fields, environment/config tooling mangling braces, copy-paste between vtgate and vtctld flags introducing a typo.
Related errors
- 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 parse vtctld FQDN template %s: %w
- failed to parse vtctld host address template %s: %w
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/93225ff6aa8be0a8.
Report an issue: GitHub.