{"record":{"id":"5656a0bbf02fc1cc","repo":"XTLS/Xray-core","slug":"invalid-tcp-header-config","errorCode":null,"errorMessage":"invalid TCP header config","messagePattern":"invalid TCP header config","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/transport_method.go","lineNumber":243,"sourceCode":"}\n\nvar tcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{\n\t\"none\": func() interface{} { return new(NoOpConnectionAuthenticator) },\n\t\"http\": func() interface{} { return new(Authenticator) },\n}, \"type\", \"\")\n\ntype TCPConfig struct {\n\tHeaderConfig        json.RawMessage `json:\"header\"`\n\tAcceptProxyProtocol bool            `json:\"acceptProxyProtocol\"`\n}\n\n// Build implements Buildable.\nfunc (c *TCPConfig) Build() (proto.Message, error) {\n\tconfig := new(tcp.Config)\n\tif len(c.HeaderConfig) > 0 {\n\t\theaderConfig, _, err := tcpHeaderLoader.Load(c.HeaderConfig)\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"invalid TCP header config\").Base(err).AtError()\n\t\t}\n\t\tts, err := headerConfig.(Buildable).Build()\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"invalid TCP header config\").Base(err).AtError()\n\t\t}\n\t\tconfig.HeaderSettings = serial.ToTypedMessage(ts)\n\t}\n\tif c.AcceptProxyProtocol {\n\t\tconfig.AcceptProxyProtocol = c.AcceptProxyProtocol\n\t}\n\treturn config, nil\n}\n\ntype SplitHTTPConfig struct {\n\tHost                 string            `json:\"host\"`\n\tPath                 string            `json:\"path\"`\n\tMode                 string            `json:\"mode\"`\n\tHeaders              map[string]string `json:\"headers\"`","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/transport_method.go#L225-L261","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"// before\n\"transportSettings\": { \"header\": \"http\" }\n// after\n\"transportSettings\": { \"header\": { \"type\": \"http\", \"request\": { \"version\": \"1.1\", \"method\": \"GET\", \"path\": [\"/\"], \"headers\": { \"Host\": [\"example.com\"] } } } }","handlingStrategy":"validation","validationCode":"// Go: validate a TCP header block before Build()\nfunc validTCPHeader(raw json.RawMessage) error {\n\tif len(raw) == 0 {\n\t\treturn nil\n\t}\n\tvar probe struct {\n\t\tType string `json:\"type\"`\n\t}\n\tif err := json.Unmarshal(raw, &probe); err != nil {\n\t\treturn fmt.Errorf(\"header must be a JSON object: %w\", err)\n\t}\n\tswitch probe.Type {\n\tcase \"none\", \"http\":\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"header.type must be \\\"none\\\" or \\\"http\\\", got %q\", probe.Type)\n\t}\n}","typeGuard":null,"tryCatchPattern":"cfg, err := tcpConf.Build()\nif err != nil && strings.Contains(err.Error(), \"invalid TCP header config\") {\n\t// err chain carries the loader reason; surface it to the user verbatim\n\tlog.Fatal(\"fix transportSettings.header: \", err)\n}","preventionTips":["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"],"tags":["config","tcp","json","header-obfuscation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}