XTLS/Xray-core · error
invalid TCP header config
Error message
invalid TCP header config
What it means
TCPConfig.Build() failed to parse the transport's "header" field. The raw JSON of "header" is fed to tcpHeaderLoader, a polymorphic loader keyed on "type" that only accepts "none" (NoOpConnectionAuthenticator) or "http" (Authenticator). This error fires in the Load phase: the JSON is not a valid header object, the "type" discriminator is missing, or it names an unregistered header type. The underlying loader error is attached via .Base(err).
Source
Thrown at infra/conf/transport_method.go:243
}
var tcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{
"none": func() interface{} { return new(NoOpConnectionAuthenticator) },
"http": func() interface{} { return new(Authenticator) },
}, "type", "")
type TCPConfig struct {
HeaderConfig json.RawMessage `json:"header"`
AcceptProxyProtocol bool `json:"acceptProxyProtocol"`
}
// Build implements Buildable.
func (c *TCPConfig) Build() (proto.Message, error) {
config := new(tcp.Config)
if len(c.HeaderConfig) > 0 {
headerConfig, _, err := tcpHeaderLoader.Load(c.HeaderConfig)
if err != nil {
return nil, errors.New("invalid TCP header config").Base(err).AtError()
}
ts, err := headerConfig.(Buildable).Build()
if err != nil {
return nil, errors.New("invalid TCP header config").Base(err).AtError()
}
config.HeaderSettings = serial.ToTypedMessage(ts)
}
if c.AcceptProxyProtocol {
config.AcceptProxyProtocol = c.AcceptProxyProtocol
}
return config, nil
}
type SplitHTTPConfig struct {
Host string `json:"host"`
Path string `json:"path"`
Mode string `json:"mode"`
Headers map[string]string `json:"headers"`View on GitHub (pinned to 7d214f8b09)
Solutions
- Make "header" a JSON object with a "type" field of "none" or "http": {"header": {"type": "none"}}
- If using type "http", ensure the value contains a valid "request" object: {"header": {"type": "http", "request": {"version": "1.1", "method": "GET", "path": ["/"], "headers": {"Host": ["example.com"]}}}
- Run the whole config through a JSON validator (jq . config.json) to rule out syntax errors in the header block
- Check the chained base error in the returned error string — it names the exact loader failure (unknown type, missing field, bad JSON)
Example fix
// before
"transportSettings": { "header": "http" }
// after
"transportSettings": { "header": { "type": "http", "request": { "version": "1.1", "method": "GET", "path": ["/"], "headers": { "Host": ["example.com"] } } } } Defensive patterns
Strategy: validation
Validate before calling
// Go: validate a TCP header block before Build()
func validTCPHeader(raw json.RawMessage) error {
if len(raw) == 0 {
return nil
}
var probe struct {
Type string `json:"type"`
}
if err := json.Unmarshal(raw, &probe); err != nil {
return fmt.Errorf("header must be a JSON object: %w", err)
}
switch probe.Type {
case "none", "http":
return nil
default:
return fmt.Errorf("header.type must be \"none\" or \"http\", got %q", probe.Type)
}
} Try / catch
cfg, err := tcpConf.Build()
if err != nil && strings.Contains(err.Error(), "invalid TCP header config") {
// err chain carries the loader reason; surface it to the user verbatim
log.Fatal("fix transportSettings.header: ", err)
} Prevention
- Always emit "header" as an object with a "type" discriminator
- Only "none" and "http" are registered — verify against tcpHeaderLoader in your build
- Lint full config JSON (jq) before feeding it to the core
When it happens
Trigger: A streamSettings.transportSettings JSON object for tcp contains a "header" key whose value fails tcpHeaderLoader.Load(): e.g. {"header": "http"} (string instead of object), {"header": {}} (missing "type"), {"header": {"type": "webrtc"}} (unknown type — only "none" and "http" are registered at transport_method.go:227-230), or malformed JSON such as a trailing comma.
Common situations: Copying an httpheader config from another proxy tool (v2rayN, clash) whose schema differs; misspelling "type" or using the old "header.type": "none" nesting wrongly; passing a string where the loader expects an object; leaving a stray comma when hand-editing JSON configs.
Related errors
- tcpFastOpen: only boolean and integer value is acceptable
- unknown format of a string list:
- invalid address:
- Invalid integer range, expected either string of form "1-2"
- invalid fakedns config
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/5656a0bbf02fc1cc.
Report an issue: GitHub.