gravitational/teleport · error

cannot route to empty target host

Error message

cannot route to empty target host

What it means

NewSSHRouteMatcherFromConfig requires a target Host in SSHRouteMatcherConfig; if cfg.Host is empty it returns errEmptyHost wrapped. An SSH route matcher must know which host traffic routes to — an empty host would produce a matcher that can never route, so construction fails fast.

Source

Thrown at api/utils/route.go:64

	// it will match servers listening on any port.
	Port string
	// Resolver can be set to override default hostname lookup
	// behavior (used in tests).
	Resolver HostResolver
	// CaseInsensitive enabled case insensitive routing when true.
	CaseInsensitive bool
	// DisableUnqualifiedLookups disables lookups for unqualified hostnames.
	DisableUnqualifiedLookups bool
}

// HostResolver provides an interface matching the net.Resolver.LookupHost method. Typically
// only used as a means of overriding dns resolution behavior in tests.
type HostResolver interface {
	// LookupHost performs a hostname lookup.  See net.Resolver.LookupHost for details.
	LookupHost(ctx context.Context, host string) (addrs []string, err error)
}

var errEmptyHost = errors.New("cannot route to empty target host")

// NewSSHRouteMatcherFromConfig sets up an ssh route matcher from the supplied configuration.
func NewSSHRouteMatcherFromConfig(cfg SSHRouteMatcherConfig) (*SSHRouteMatcher, error) {
	if cfg.Host == "" {
		return nil, trace.Wrap(errEmptyHost)
	}

	if cfg.Resolver == nil {
		cfg.Resolver = net.DefaultResolver
	}

	m := newSSHRouteMatcher(cfg)
	return &m, nil
}

// NewSSHRouteMatcher builds a new matcher for ssh routing decisions.
func NewSSHRouteMatcher(host, port string, caseInsensitive bool) SSHRouteMatcher {
	return newSSHRouteMatcher(SSHRouteMatcherConfig{

View on GitHub (pinned to 1283425b60)

Solutions

  1. Set cfg.Host to the target hostname/IP before calling NewSSHRouteMatcherFromConfig.
  2. Validate the upstream input (address string, server spec) so an empty/failed parse doesn't propagate an empty host into the route config.
  3. Reject requests earlier in the API layer with a clearer user-facing message like "target host is required".

Example fix

// before
m, err := utils.NewSSHRouteMatcherFromConfig(utils.SSHRouteMatcherConfig{Host: hostFromAddr})
// after
if hostFromAddr == "" {
    return trace.BadParameter("target host is required")
}
m, err := utils.NewSSHRouteMatcherFromConfig(utils.SSHRouteMatcherConfig{Host: hostFromAddr})
Defensive patterns

Strategy: validation

Validate before calling

if routeCfg.Host == "" { return trace.BadParameter("SSH route target host is required") }

Try / catch

m, err := utils.NewSSHRouteMatcherFromConfig(cfg)
if err != nil && strings.Contains(err.Error(), "empty target host") {
    return trace.BadParameter("cannot route: target host missing from request")
}

Prevention

When it happens

Trigger: Constructing an SSHRouteMatcher via NewSSHRouteMatcherFromConfig with SSHRouteMatcherConfig{Host: ""} — e.g. building a dial/route descriptor from a parsed address or server object whose hostname field is missing.

Common situations: Proxy code routing agentless SSH sessions where the target node address was not resolved; config files or API payloads omitting the host; parsing failures upstream silently leaving Host empty.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/7f20586b2fe7aac3. Report an issue: GitHub.