{"record":{"id":"5484bdadc0532f6e","repo":"vitessio/vitess","slug":"failed-to-generate-vtgate-consul-datacenter-from-t","errorCode":null,"errorMessage":"failed to generate vtgate consul datacenter from template: %w","messagePattern":"failed to generate vtgate consul datacenter from template: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/cluster/discovery/discovery_consul.go","lineNumber":128,"sourceCode":"\t\t\"Go template string to produce a dialable address from a *vtadminpb.Vtctld \"+\n\t\t\t\"NOTE: the .FQDN field will never be set in the addr template context.\")\n\tvtctldDatacenterTmplStr := flags.String(\"vtctld-datacenter-tmpl\", \"\",\n\t\t\"Go template string to generate the datacenter for vtgate consul queries. \"+\n\t\t\t\"The cluster name is provided to the template via {{ .Cluster }}. \"+\n\t\t\t\"Used once during initialization.\")\n\tvtctldFQDNTmplStr := flags.String(\"vtctld-fqdn-tmpl\", \"\",\n\t\t\"Optional Go template string to produce an FQDN to access the vtctld from a browser. \"+\n\t\t\t\"E.g. \\\"{{ .Hostname }}.example.com\\\".\")\n\n\tif err := flags.Parse(args); err != nil {\n\t\treturn nil, err\n\t}\n\n\t/* gates options */\n\tif *vtgateDatacenterTmplStr != \"\" {\n\t\tdisco.vtgateDatacenter, err = generateConsulDatacenter(\"vtgate\", cluster, *vtgateDatacenterTmplStr)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to generate vtgate consul datacenter from template: %w\", err)\n\t\t}\n\t}\n\n\tif *vtgateFQDNTmplStr != \"\" {\n\t\tdisco.vtgateFQDNTmpl, err = template.New(\"consul-vtgate-fqdn-template-\" + cluster.Id).Parse(*vtgateFQDNTmplStr)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse vtgate FQDN template %s: %w\", *vtgateFQDNTmplStr, err)\n\t\t}\n\t}\n\n\tdisco.vtgateAddrTmpl, err = template.New(\"consul-vtgate-address-template-\" + cluster.Id).Parse(*vtgateAddrTmplStr)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse vtgate host address template %s: %w\", *vtgateAddrTmplStr, err)\n\t}\n\n\t/* vtctld options */\n\tif *vtctldDatacenterTmplStr != \"\" {\n\t\tdisco.vtctldDatacenter, err = generateConsulDatacenter(\"vtctld\", cluster, *vtctldDatacenterTmplStr)","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/cluster/discovery/discovery_consul.go#L110-L146","documentation":"NewConsul builds the consul discovery implementation and renders optional vtgate datacenter templates against the cluster proto. When generateConsulDatacenter (parse or execute) fails for the vtgate datacenter template, the error is wrapped with this message. It means the vtgate datacenter Go template string itself could not be parsed or rendered with the cluster data.","triggerScenarios":"Passing a non-empty vtgate-datacenter-template flag value whose template fails to parse (bad Go template syntax, unknown function) or fails to execute (e.g. field access on nil/missing data) during NewConsul.","commonSituations":"Malformed template like \"{{ .Cluster.Names }\" (unclosed action), referencing a field that does not exist on vtadminpb.Cluster, or quoting/escaping issues in YAML/env config mangling the template.","solutions":["Fix the vtgate datacenter template syntax so it is a valid Go text/template (balanced {{ }}, valid field paths).","Reference only fields that exist on vtadminpb.Cluster (e.g. {{ .Cluster.Id }}); inspect the proto for available fields.","Clear the vtgate datacenter template flag if the option is not needed — it is only processed when non-empty.","Inspect the wrapped %w error, which pinpoints parse vs execute failure and the offending offset."],"exampleFix":"// before\n--vtgate-datacenter-template=\"{{ .Cluster.Id\"  // unclosed action\n// after\n--vtgate-datacenter-template=\"{{ .Cluster.Id }}\"","handlingStrategy":"validation","validationCode":"tmpl := os.Getenv(\"VTGATE_DC_TEMPLATE\")\nif tmpl != \"\" {\n    if _, err := template.New(\"check\").Parse(tmpl); err != nil {\n        return fmt.Errorf(\"invalid vtgate dc template: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"disco, err := NewConsul(cluster, args)\nif err != nil {\n    var perr *template.Template\n    if strings.Contains(err.Error(), \"vtgate consul datacenter\") {\n        log.Fatalf(\"bad vtgate datacenter template: %v\", err)\n    }\n    return err\n}","preventionTips":["Unit-test all configured templates with text/template Parse before startup.","Use only fields documented on vtadminpb.Cluster in templates.","Quote templates carefully in YAML/shell so braces are preserved.","Leave templates empty when the feature is not needed."],"tags":["go","template","consul","discovery","config"],"backgroundTag":"template-parse-failed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}