XTLS/Xray-core · error
"headers" can't contain "host"
Error message
"headers" can't contain "host"
What it means
SplitHTTPConfig.Build() iterates the "headers" map and rejects any key equal (case-insensitively) to "host" at transport_method.go:328-332. The HTTP Host header is governed by the dedicated "host" field (priority on the client: host > serverName > address, per the comment), so duplicating it inside "headers" is ambiguous and forbidden.
Source
Thrown at infra/conf/transport_method.go:330
}
extra.Host = c.Host
extra.Path = c.Path
extra.Mode = c.Mode
c = &extra
}
switch c.Mode {
case "":
c.Mode = "auto"
case "auto", "packet-up", "stream-up", "stream-one":
default:
return nil, errors.New("unsupported mode: " + c.Mode)
}
// Priority (client): host > serverName > address
for k := range c.Headers {
if strings.ToLower(k) == "host" {
return nil, errors.New(`"headers" can't contain "host"`)
}
}
if c.XPaddingBytes != (Int32Range{}) && (c.XPaddingBytes.From <= 0 || c.XPaddingBytes.To <= 0) {
return nil, errors.New("xPaddingBytes cannot be disabled")
}
if c.XPaddingKey == "" {
c.XPaddingKey = "x_padding"
}
if c.XPaddingHeader == "" {
c.XPaddingHeader = "X-Padding"
}
switch c.XPaddingPlacement {
case "":
c.XPaddingPlacement = "queryInHeader"View on GitHub (pinned to 7d214f8b09)
Solutions
- Remove the Host entry from "headers" and use the top-level "host" field instead
- Keep all other camouflage headers (User-Agent, Accept, etc.) in "headers" as-is
- Search case-insensitively when auditing — "HOST", "Host", "hOsT" all trigger it
Example fix
// before
"host": "dl.example.com", "headers": { "Host": "dl.example.com", "User-Agent": "curl/8" }
// after
"host": "dl.example.com", "headers": { "User-Agent": "curl/8" } Defensive patterns
Strategy: validation
Validate before calling
// Go: reject Host keys before Build()
for k := range cfg.Headers {
if strings.EqualFold(k, "host") {
return errors.New("move Host to the top-level host field")
}
} Prevention
- Never include Host in splithttp headers — use the host field
- Audit imported header sets case-insensitively for 'host'
When it happens
Trigger: splithttp transportSettings with "headers": {"Host": "example.com"} or {"host": "..."} — any casing passes strings.ToLower. Triggers regardless of mode, before padding checks.
Common situations: Copying a full browser header set (including Host) into headers for camouflage; migrating from websocket/http transport configs where a Host header was the normal way to set SNI/authority; merging example configs that predate this restriction.
Related errors
- empty HTTP header value: + key
- HTTP settings: "servers" should have one and only one member
- HTTP servers: "users" should have one member at most. Multip
- failed to parse HTTP user
- failed to parse HTTP account
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/84a914dafc3842f2.
Report an issue: GitHub.