{"record":{"id":"01ffe6322a12b46e","repo":"XTLS/Xray-core","slug":"len-item-packet-0-item-rand-to-0","errorCode":null,"errorMessage":"len(item.Packet) > 0 && item.Rand.To > 0","messagePattern":"len\\(item\\.Packet\\) > 0 && item\\.Rand\\.To > 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/transport_finalmask.go","lineNumber":311,"sourceCode":"}\n\ntype NoiseItem struct {\n\tRand      Int32Range      `json:\"rand\"`\n\tRandRange *Int32Range     `json:\"randRange\"`\n\tType      string          `json:\"type\"`\n\tPacket    json.RawMessage `json:\"packet\"`\n\tDelay     Int32Range      `json:\"delay\"`\n}\n\ntype NoiseMask struct {\n\tReset Int32Range  `json:\"reset\"`\n\tNoise []NoiseItem `json:\"noise\"`\n}\n\nfunc (c *NoiseMask) Build() (proto.Message, error) {\n\tfor _, item := range c.Noise {\n\t\tif len(item.Packet) > 0 && item.Rand.To > 0 {\n\t\t\treturn nil, errors.New(\"len(item.Packet) > 0 && item.Rand.To > 0\")\n\t\t}\n\t}\n\n\tnoiseSlice := make([]*noise.Item, 0, len(c.Noise))\n\tfor _, item := range c.Noise {\n\t\tif item.RandRange == nil {\n\t\t\titem.RandRange = &Int32Range{From: 0, To: 255}\n\t\t}\n\t\tif item.RandRange.From < 0 || item.RandRange.To > 255 {\n\t\t\treturn nil, errors.New(\"invalid randRange\")\n\t\t}\n\t\tvar err error\n\t\tif item.Packet, err = PraseByteSlice(item.Packet, item.Type); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tnoiseSlice = append(noiseSlice, &noise.Item{\n\t\t\tRandMin:      int64(item.Rand.From),\n\t\t\tRandMax:      int64(item.Rand.To),","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/transport_finalmask.go#L293-L329","documentation":"NoiseMask.Build (infra/conf/transport_finalmask.go:311) enforces mutual exclusivity per noise item: an item may carry a fixed \"packet\" OR generate \"rand\" random bytes (rand.to>0), never both. Violating this returns the literal condition string \"len(item.Packet) > 0 && item.Rand.To > 0\" as the error.","triggerScenarios":"A noise item like {\"packet\":\"abc\",\"type\":\"str\",\"rand\":{\"to\":16}}. rand.to defaults to 0, so \"rand\":{} or omitting rand keeps a fixed packet legal; any positive upper bound alongside a non-empty packet triggers it.","commonSituations":"Template items that set all fields for 'flexibility'; merging a fixed-padding item with a random-padding item into one; editing configs where rand was left from a previous random item.","solutions":["Split into two items: one with packet only, one with rand only","Delete \"packet\" (and \"type\") when using rand, or set \"rand\":{\"from\":0,\"to\":0} / omit rand when using packet"],"exampleFix":"// before\n\"noise\": [ { \"type\":\"str\", \"packet\":\"hi\", \"rand\": {\"to\":16} } ]\n// after\n\"noise\": [ { \"type\":\"str\", \"packet\":\"hi\" }, { \"rand\": {\"to\":16} } ]","handlingStrategy":"validation","validationCode":"for (const it of cfg.noise ?? []) {\n  const hasPacket = it.packet != null && it.packet !== '' && !(Array.isArray(it.packet) && it.packet.length === 0);\n  if (hasPacket && (it.rand?.to ?? 0) > 0) throw new Error('noise item cannot set both packet and rand.to>0');\n}","typeGuard":"const isExclusiveNoiseItem = (it:any) => !((it.packet != null && it.packet !== '' && !(Array.isArray(it.packet)&&it.packet.length===0)) && ((it.rand?.to ?? 0) > 0));","tryCatchPattern":null,"preventionTips":["One purpose per noise item: fixed bytes or random bytes","Split mixed items into two entries"],"tags":["xray","go","transport","noise","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}