XTLS/Xray-core · error
sessionIDTable or sessionIDLength is too small
Error message
sessionIDTable or sessionIDLength is too small
What it means
When "sessionIDTable" is set, SplitHTTPConfig.Build() resolves predefined tables via splithttp.PredefinedTable, then computes roomSize = sum over k in [from,to] of tableLen^k (transport_method.go:512-521) and requires at least 2^31 (2<<30) possible session IDs (line 414). This error means the table plus the sessionIDLength range yields too little entropy — a small character table and/or a short ID length make session IDs guessable/enumerable.
Source
Thrown at infra/conf/transport_method.go:415
}
if c.SessionIDPlacement != "path" && c.SessionIDKey == "" {
switch c.SessionIDPlacement {
case "cookie", "query":
c.SessionIDKey = "x_session"
case "header":
c.SessionIDKey = "X-Session"
}
}
if c.SessionIDTable != "" {
if predefined, ok := splithttp.PredefinedTable[c.SessionIDTable]; ok {
c.SessionIDTable = predefined
}
room := roomSize(len(c.SessionIDTable), c.SessionIDLength.From, c.SessionIDLength.To)
// 2.1B possiblities should be enough
if room.Cmp(big.NewInt(2<<30)) < 0 {
return nil, errors.New("sessionIDTable or sessionIDLength is too small")
}
if c.SessionIDLength.From <= 0 {
return nil, errors.New("sessionIDLength.from must be greater than 0")
}
for i := 0; i < len(c.SessionIDTable); i++ {
if c.SessionIDTable[i] >= 0x80 {
return nil, errors.New("sessionIDTable must contain only ASCII characters")
}
}
}
if c.SeqPlacement != "path" && c.SeqKey == "" {
switch c.SeqPlacement {
case "cookie", "query":
c.SeqKey = "x_seq"
case "header":
c.SeqKey = "X-Seq"
}View on GitHub (pinned to 7d214f8b09)
Solutions
- Set "sessionIDLength": {"from": N, "to": N} large enough: with a 64-char table, from=6 (64^6 ≈ 6.9e10) already passes
- Or use a bigger "sessionIDTable" string / a predefined table name resolvable in splithttp.PredefinedTable
- Rule of thumb: tableLen^from must reach ~2^31, so len(table) >= 2^(31/from)
Example fix
// before
"sessionIDTable": "0123456789", "sessionIDLength": { "from": 1, "to": 2 }
// after
"sessionIDTable": "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-", "sessionIDLength": { "from": 6, "to": 8 } Defensive patterns
Strategy: validation
Validate before calling
// Go: mirror roomSize() and require >= 2^31 possibilities
func sessionRoomOK(table string, from, to int32) bool {
base := big.NewInt(int64(len(table)))
sum := new(big.Int)
term := new(big.Int)
for k := from; k <= to; k++ {
if k < 0 {
continue
}
term.Exp(base, big.NewInt(int64(k)), nil)
sum.Add(sum, term)
}
return sum.Cmp(big.NewInt(2<<30)) >= 0
} Prevention
- Always pair sessionIDTable with an explicit sessionIDLength range
- Ensure tableLen^from >= ~2.1e9 (e.g. 64-char table with from>=6)
- Prefer predefined tables, which are sized to pass
When it happens
Trigger: E.g. sessionIDTable "0123456789" (10 chars) with sessionIDLength {from:1,to:1}: room = 10 < 2^31. Or a 2-char custom table with any practical length range; or from/to left at 0/0 (room=0 since the loop at line 516 never runs for min=0? — with min=0,max=0 it computes base^0=1). Any combination whose summed possibilities stay under ~2.1 billion fails.
Common situations: Users shortening ID length to make URLs smaller; using tiny custom tables for 'prettier' IDs; setting sessionIDTable but forgetting sessionIDLength so the default zero range yields a tiny room; must pair a long-enough table (or predefined table) with an adequate length range.
Related errors
- unsupported session placement:
- sessionIDLength.from must be greater than 0
- sessionIDTable must contain only ASCII characters
- Failed to unmarshal "extra".
- unsupported mode:
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/6560506a715259fa.
Report an issue: GitHub.