XTLS/Xray-core · critical · errors.Error

no target server found

Error message

no target server found

What it means

The HTTP outbound (proxy/http, i.e. an HTTP CONNECT client) was constructed with a ClientConfig whose Server field is nil. NewClient requires a server spec (address+port of the HTTP proxy) before it can dial anything, so a nil server aborts handler creation.

Source

Thrown at proxy/http/client.go:53

	server        *protocol.ServerSpec
	policyManager policy.Manager
	header        []*Header
}

type h2Conn struct {
	rawConn net.Conn
	h2Conn  *http2.ClientConn
}

var (
	cachedH2Mutex sync.Mutex
	cachedH2Conns map[net.Destination]h2Conn
)

// NewClient create a new http client based on the given config.
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
	if config.Server == nil {
		return nil, errors.New(`no target server found`)
	}
	server, err := protocol.NewServerSpecFromPB(config.Server)
	if err != nil {
		return nil, errors.New("failed to get server spec").Base(err)
	}

	v := core.MustFromContext(ctx)
	return &Client{
		server:        server,
		policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
		header:        config.Header,
	}, nil
}

// Process implements proxy.Outbound.Process. We first create a socket tunnel via HTTP CONNECT method, then redirect all inbound traffic to that tunnel.
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
	outbounds := session.OutboundsFromContext(ctx)
	ob := outbounds[len(outbounds)-1]

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Add settings.servers: [ { "address": "proxy.example.com", "port": 3128, "users": [...] } ] to the outbound
  2. Verify field names against the current Xray HTTP outbound schema (it is an array named servers)
  3. If building ClientConfig in Go, set .Server from a valid serializable server spec before NewClient

Example fix

// before
{ "protocol": "http", "settings": {} }
// after
{ "protocol": "http", "settings": { "servers": [ { "address": "proxy.example.com", "port": 3128 } ] } }
Defensive patterns

Strategy: validation

Validate before calling

```go
if cfg.Server == nil {
    return errors.New("http outbound requires settings.servers[0]")
}
client, err := http.NewClient(ctx, cfg)
```

Type guard

```go
func hasHTTPServer(cfg *http.ClientConfig) bool {
    return cfg != nil && cfg.Server != nil
}
```

Prevention

When it happens

Trigger: Outbound config with "protocol":"http" but missing settings.servers[] (or an empty array), or programmatic construction passing a ClientConfig without Server.

Common situations: JSON config typo ("server" instead of "servers"), empty servers list after templating/generation, version upgrade that renamed the field.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/b9ca8d2080fc52d4. Report an issue: GitHub.