XTLS/Xray-core · error

no target server found

Error message

no target server found

What it means

Returned by NewClient for the trojan outbound when the ClientConfig carries no Server field. The trojan client is a pure proxy client — it needs exactly one target server to dial, so a missing server is a hard configuration error.

Source

Thrown at proxy/trojan/client.go:32

	"github.com/xtls/xray-core/common/signal"
	"github.com/xtls/xray-core/common/task"
	core "github.com/xtls/xray-core/core"
	"github.com/xtls/xray-core/features/policy"
	"github.com/xtls/xray-core/transport"
	"github.com/xtls/xray-core/transport/internet"
	"github.com/xtls/xray-core/transport/internet/stat"
)

// Client is a inbound handler for trojan protocol
type Client struct {
	server        *protocol.ServerSpec
	policyManager policy.Manager
}

// NewClient create a new trojan client.
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)
	client := &Client{
		server:        server,
		policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
	}
	return client, nil
}

// Process implements OutboundHandler.Process().
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 the required server object to the trojan outbound settings with address and port.
  2. Validate the config with xray run -test (or -c config.json -format json) before deploying.
  3. If generated by a panel/subscription converter, update it or regenerate the subscription.

Example fix

// before
{ "protocol": "trojan", "settings": { "servers": [] } }

// after
{ "protocol": "trojan", "settings": { "servers": [ { "address": "s.example.com", "port": 443, "password": "..." } ] } }
Defensive patterns

Strategy: validation

Validate before calling

func ValidateTrojanOutbound(cfg *trojan.ClientConfig) error {
	if cfg.Server == nil {
		return errors.New("trojan outbound requires settings.servers[0]")
	}
	return nil
}

Prevention

When it happens

Trigger: Creating a trojan outbound handler whose config JSON lacks the "server" (address/port) object — e.g. only users or streamSettings were provided.

Common situations: Hand-written or panel-generated config that omitted the server block; config migration where the server field was renamed/dropped; YAML-to-JSON conversion losing the nested object.

Related errors


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