{"record":{"id":"6101177d262807f9","repo":"XTLS/Xray-core","slug":"sessionidlength-from-must-be-greater-than-0","errorCode":null,"errorMessage":"sessionIDLength.from must be greater than 0","messagePattern":"sessionIDLength\\.from must be greater than 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/transport_method.go","lineNumber":418,"sourceCode":"\t\tswitch c.SessionIDPlacement {\n\t\tcase \"cookie\", \"query\":\n\t\t\tc.SessionIDKey = \"x_session\"\n\t\tcase \"header\":\n\t\t\tc.SessionIDKey = \"X-Session\"\n\t\t}\n\t}\n\n\tif c.SessionIDTable != \"\" {\n\t\tif predefined, ok := splithttp.PredefinedTable[c.SessionIDTable]; ok {\n\t\t\tc.SessionIDTable = predefined\n\t\t}\n\t\troom := roomSize(len(c.SessionIDTable), c.SessionIDLength.From, c.SessionIDLength.To)\n\t\t// 2.1B possiblities should be enough\n\t\tif room.Cmp(big.NewInt(2<<30)) < 0 {\n\t\t\treturn nil, errors.New(\"sessionIDTable or sessionIDLength is too small\")\n\t\t}\n\t\tif c.SessionIDLength.From <= 0 {\n\t\t\treturn nil, errors.New(\"sessionIDLength.from must be greater than 0\")\n\t\t}\n\t\tfor i := 0; i < len(c.SessionIDTable); i++ {\n\t\t\tif c.SessionIDTable[i] >= 0x80 {\n\t\t\t\treturn nil, errors.New(\"sessionIDTable must contain only ASCII characters\")\n\t\t\t}\n\t\t}\n\t}\n\n\tif c.SeqPlacement != \"path\" && c.SeqKey == \"\" {\n\t\tswitch c.SeqPlacement {\n\t\tcase \"cookie\", \"query\":\n\t\t\tc.SeqKey = \"x_seq\"\n\t\tcase \"header\":\n\t\t\tc.SeqKey = \"X-Seq\"\n\t\t}\n\t}\n\n\tif c.UplinkDataPlacement != splithttp.PlacementBody && c.UplinkDataKey == \"\" {","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/transport_method.go#L400-L436","documentation":"Inside the sessionIDTable block, after the entropy check, SplitHTTPConfig.Build() requires sessionIDLength.From > 0 at transport_method.go:417-419. Zero-length session IDs cannot be generated from a table, so from must be at least 1. Note the ordering: the entropy check (error 413) runs first, so a zero range usually surfaces as 413 unless the table is large enough that even degenerate terms pass.","triggerScenarios":"\"sessionIDTable\": <table> with \"sessionIDLength\": {\"from\": 0, \"to\": 5} or the field omitted (zero-value Int32Range has From=0) while a table is set and the room check happens to pass.","commonSituations":"Setting sessionIDTable without knowing sessionIDLength is required alongside; explicitly zeroing from intending 'auto'.","solutions":["Set \"sessionIDLength\": {\"from\": 1, ...} or higher (and keep the entropy rule satisfied)","Remember from is the minimum generated ID length — it must be >= 1"],"exampleFix":"// before\n\"sessionIDTable\": \"abcdef\", \"sessionIDLength\": { \"from\": 0, \"to\": 0 }\n// after\n\"sessionIDTable\": \"abcdef\", \"sessionIDLength\": { \"from\": 12, \"to\": 16 }","handlingStrategy":"validation","validationCode":"// Go: from must be positive when a table is set\nif cfg.SessionIDTable != \"\" && cfg.SessionIDLength.From <= 0 {\n\treturn errors.New(\"set sessionIDLength.from >= 1\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["sessionIDTable without sessionIDLength leaves From=0 — always set both"],"tags":["config","splithttp","session","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}