{"record":{"id":"a4f874b0db4824ed","repo":"XTLS/Xray-core","slug":"invalid-header","errorCode":null,"errorMessage":"invalid header ","messagePattern":"invalid header ","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/transport_finalmask.go","lineNumber":626,"sourceCode":"\tswitch strings.ToLower(c.Header) {\n\tcase \"dns\":\n\t\tdomain := c.Value\n\t\tif len(domain) == 0 {\n\t\t\tdomain = \"www.baidu.com\"\n\t\t}\n\t\treturn &header.Config{ID: 0, Domain: domain}, nil\n\tcase \"dtls\":\n\t\treturn &header.Config{ID: 1}, nil\n\tcase \"srtp\":\n\t\treturn &header.Config{ID: 2}, nil\n\tcase \"utp\":\n\t\treturn &header.Config{ID: 3}, nil\n\tcase \"wechat\":\n\t\treturn &header.Config{ID: 4}, nil\n\tcase \"wireguard\":\n\t\treturn &header.Config{ID: 5}, nil\n\tdefault:\n\t\treturn nil, errors.New(\"invalid header \", c.Header)\n\t}\n}\n\ntype Salamander struct {\n\tPassword   string     `json:\"password\"`\n\tPacketSize Int32Range `json:\"packetSize\"`\n}\n\nfunc (c *Salamander) Build() (proto.Message, error) {\n\tif c.PacketSize.To > 0 {\n\t\tif c.PacketSize.From <= 0 || c.PacketSize.To > 2048 {\n\t\t\treturn nil, errors.New(\"gecko: invalid min/max packet size\")\n\t\t}\n\t\treturn &salamander.GeckoConfig{\n\t\t\tPassword:      c.Password,\n\t\t\tMinPacketSize: c.PacketSize.From,\n\t\t\tMaxPacketSize: c.PacketSize.To,\n\t\t}, nil","sourceCodeStart":608,"sourceCodeEnd":644,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/transport_finalmask.go#L608-L644","documentation":"A header-preset Build in infra/conf/transport_finalmask.go:626 maps well-known camouflage header names to numeric IDs (\"\"->domain-based 0, dtls->1, srtp->2, utp->3, wechat->4, wireguard->5) for the header.Config used by mkcp-style masking. Any unrecognized \"header\" value fails with \"invalid header \" + the offending name.","triggerScenarios":"\"header\":\"wechat-video\", \"header\":\"DTLS\" (case-sensitive switch), \"header\":\"video\". Omitting header or leaving it empty is valid and uses the domain form.","commonSituations":"Copying kcp header presets from older docs/forks with renamed options; case mismatch; typos in the preset name.","solutions":["Use exactly one of: dtls, srtp, utp, wechat, wireguard (lowercase), or omit \"header\"","Verify the header value against the current preset list for your Xray version","Prefer copy-paste from the official transport docs over retyping"],"exampleFix":"// before\n\"header\": { \"type\": \"none\", \"header\": \"srtp\" }\n// after (drop the invalid wrapper/preset)\n\"header\": { \"type\": \"none\" }  // or \"header\": { \"type\": \"srpcamouflage\", \"header\": \"srtp\" } per docs\n// simplest: ensure the preset string is exactly \"srtp\" lowercase in the field this builder reads","handlingStrategy":"validation","validationCode":"const HEADERS = new Set(['', 'dtls', 'srtp', 'utp', 'wechat', 'wireguard']);\nif (!HEADERS.has(headerCfg.header ?? '')) throw new Error(`invalid header preset: ${headerCfg.header}`);","typeGuard":"const isHeaderPreset = (h: string) => ['', 'dtls', 'srtp', 'utp', 'wechat', 'wireguard'].includes(h);","tryCatchPattern":null,"preventionTips":["Copy preset names verbatim from current docs (lowercase)","Re-validate header presets after upgrading Xray versions"],"tags":["xray","go","transport","header","mkcp","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}