XTLS/Xray-core · error

inbound gateway not specified

Error message

inbound gateway not specified

What it means

Thrown by the SOCKS inbound's processTCP when the session's inbound gateway (the address/port this inbound serves, attached by the listener) is missing or invalid. The gateway is needed to build the ServerSession that answers SOCKS5 BIND/UDP ASSOCIATE with a reachable bind address.

Source

Thrown at proxy/socks/server.go:105

		if firstbyte[0] != 5 && firstbyte[0] != 4 { // Check if it is Socks5/4/4a
			errors.LogDebug(ctx, "Not Socks request, try to parse as HTTP request")
			return s.httpServer.ProcessWithFirstbyte(ctx, network, conn, dispatcher, firstbyte...)
		}
		return s.processTCP(ctx, conn, dispatcher, firstbyte)
	default:
		return errors.New("unknown network: ", network)
	}
}

func (s *Server) processTCP(ctx context.Context, conn stat.Connection, dispatcher routing.Dispatcher, firstbyte []byte) error {
	plcy := s.policy()
	if err := conn.SetReadDeadline(time.Now().Add(plcy.Timeouts.Handshake)); err != nil {
		errors.LogInfoInner(ctx, err, "failed to set deadline")
	}

	inbound := session.InboundFromContext(ctx)
	if inbound == nil || !inbound.Gateway.IsValid() {
		return errors.New("inbound gateway not specified")
	}

	svrSession := &ServerSession{
		config:       s.config,
		address:      inbound.Gateway.Address,
		port:         inbound.Gateway.Port,
		localAddress: net.IPAddress(conn.LocalAddr().(*net.TCPAddr).IP),
	}

	// Firstbyte is for forwarded conn from SOCKS inbound
	// Because it needs first byte to choose protocol
	// We need to add it back
	reader := &buf.BufferedReader{
		Reader: buf.NewReader(conn),
		Buffer: buf.MultiBuffer{buf.FromBytes(firstbyte)},
	}
	request, tempUDPConn, err := svrSession.Handshake(reader, conn)
	defer common.CloseIfExists(tempUDPConn)

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Route connections through the standard inbound handler manager (core.RegisterInboundHandler + normal listener) so Gateway is populated.
  2. If embedding, set session.Inbound{Gateway: net.DestinationFromAddr(conn.LocalAddr())} into the context before calling Process.
  3. Align your fork/vendor copy with the current core version — older code may omit gateway initialization.

Example fix

// embedding code, before
ctx = session.ContextWithInbound(ctx, &session.Inbound{Source: src})
s.Process(ctx, conn, dispatcher)

// after
ctx = session.ContextWithInbound(ctx, &session.Inbound{
	Source:  src,
	Gateway: net.DestinationFromAddr(conn.LocalAddr()), // required for BIND/UDP replies
})
s.Process(ctx, conn, dispatcher)
Defensive patterns

Strategy: validation

Validate before calling

// when embedding: attach a valid gateway before Process
inbound := &session.Inbound{
	Source:  net.DestinationFromAddr(conn.RemoteAddr()),
	Gateway: net.DestinationFromAddr(conn.LocalAddr()),
}
if !inbound.Gateway.IsValid() {
	return errors.New("refusing to process without gateway")
}

Prevention

When it happens

Trigger: session.InboundFromContext(ctx) returns nil or an Inbound whose Gateway.IsValid() is false — the context was not populated with a gateway by a standard internet listener, typically when the handler is embedded or driven by non-standard code rather than the normal inbound manager.

Common situations: Third-party code embedding Xray-core and dispatching connections manually without setting inbound.Gateway; a custom transport/launcher that skips the standard listener initialization; version mismatch after an API change in session plumbing.

Related errors


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