grpc/grpc-go · error
xds: field clientListenerResourceNameTemplate
Error message
xds: field clientListenerResourceNameTemplate %q of authority %q doesn't start with prefix %q
What it means
Returned by Config.UnmarshalJSON when an authority's client_listener_resource_name_template, if set, does not start with the required prefix 'xdstp://<authority_name>/'. The prefix is derived from the authority's map key, URL-path-escaped.
Solutions
- Either remove the client_listener_resource_name_template field (it defaults to 'xdstp://<authority_name>/envoy.config.listener.v3.Listener/%s') or set it to start with 'xdstp://<authority_name>/'.
- Match the authority key exactly in the prefix, including URL path-escaping for special characters.
- Keep the '%s' substitution token so the service authority can be injected.
- Use the same spelling/casing for the authority key and the prefix.
Example fix
// before (key 'auth1' but template uses 'auth2')
"authorities":{"auth1":{"client_listener_resource_name_template":"xdstp://auth2/envoy.config.listener.v3.Listener/%s"}}
// after
"authorities":{"auth1":{"client_listener_resource_name_template":"xdstp://auth1/envoy.config.listener.v3.Listener/%s"}} Defensive patterns
Strategy: validation
Validate before calling
// For each authority, confirm its template prefix matches its key.
func validateAuthorityPrefixes(auths map[string]map[string]string) error {
for name, a := range auths {
tmpl := a["client_listener_resource_name_template"]
if tmpl == "" {
continue // default is fine
}
want := "xdstp://" + url.PathEscape(name) + "/"
if !strings.HasPrefix(tmpl, want) {
return fmt.Errorf("authority %q template must start with %q", name, want)
}
}
return nil
} Try / catch
if _, err := bootstrap.NewConfigFromContents(data); err != nil {
if strings.Contains(err.Error(), "clientListenerResourceNameTemplate") {
// align the authority template prefix with the authority key.
}
} Prevention
- Omit client_listener_resource_name_template to take the safe default.
- When renaming an authority key, update every template prefix.
- URL-path-escape the authority name in the prefix.
When it happens
Trigger: Triggered at bootstrap.go:644 when authority.ClientListenerResourceNameTemplate is non-empty and does not have the prefix strings.HasPrefix(template, 'xdstp://<name>/').
Common situations: Template copied from another authority without updating the prefix to match the new authority key; template uses an old-style (non-xdstp) name; authority key renamed but template not updated; special characters in the authority name not path-escaped consistently.
Related errors
- failed to build credentials bundle from bootstrap for
- missing server_listener_resource_name_template in the…
- xds: `channel_creds` field in server config cannot be empty
- xds: config parsing for certificate provider plugin
- xds: error normalizing JSON bootstrap configuration
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/d803e0d8880e1589.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/bootstrap/bootstrap.go:644
// Default value of the default client listener name template is "%s".
if c.clientDefaultListenerResourceNameTemplate == "" {
c.clientDefaultListenerResourceNameTemplate = "%s"
}
if len(c.xDSServers) == 0 {
return fmt.Errorf("xds: required field `xds_servers` not found in bootstrap configuration: %s", string(data))
}
// Post-process the authorities' client listener resource template field:
// - if set, it must start with "xdstp://<authority_name>/"
// - if not set, it defaults to "xdstp://<authority_name>/envoy.config.listener.v3.Listener/%s"
for name, authority := range c.authorities {
prefix := fmt.Sprintf("xdstp://%s", url.PathEscape(name))
if authority.ClientListenerResourceNameTemplate == "" {
authority.ClientListenerResourceNameTemplate = prefix + "/envoy.config.listener.v3.Listener/%s"
continue
}
if !strings.HasPrefix(authority.ClientListenerResourceNameTemplate, prefix) {
return fmt.Errorf("xds: field clientListenerResourceNameTemplate %q of authority %q doesn't start with prefix %q", authority.ClientListenerResourceNameTemplate, name, prefix)
}
}
return nil
}
// GetConfiguration returns the bootstrap configuration initialized by reading
// the bootstrap file found at ${GRPC_XDS_BOOTSTRAP} or bootstrap contents
// specified at ${GRPC_XDS_BOOTSTRAP_CONFIG}. If both env vars are set, the
// former is preferred.
//
// This function tries to process as much of the bootstrap file as possible (in
// the presence of the errors) and may return a Config object with certain
// fields left unspecified, in which case the caller should use some sane
// defaults.
//
// This function returns an error if it's unable to parse the contents of the
// bootstrap config. It returns (nil, nil) if none of the env vars are set.
func GetConfiguration() (*Config, error) {View on GitHub (pinned to 0c51461d27)