{"record":{"id":"17c6abe5a3f804aa","repo":"XTLS/Xray-core","slug":"sessionidtable-must-contain-only-ascii-characters","errorCode":null,"errorMessage":"sessionIDTable must contain only ASCII characters","messagePattern":"sessionIDTable must contain only ASCII characters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/transport_method.go","lineNumber":422,"sourceCode":"\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 == \"\" {\n\t\tswitch c.UplinkDataPlacement {\n\t\tcase splithttp.PlacementCookie:\n\t\t\tc.UplinkDataKey = \"x_data\"\n\t\tcase splithttp.PlacementAuto, splithttp.PlacementHeader:","sourceCodeStart":404,"sourceCodeEnd":440,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/transport_method.go#L404-L440","documentation":"Inside the sessionIDTable block, SplitHTTPConfig.Build() scans every byte of the (predefined-resolved) table and rejects any byte >= 0x80 at transport_method.go:420-424. Session IDs built from the table end up in URLs, cookies, and headers, so the alphabet must be 7-bit ASCII.","triggerScenarios":"A custom \"sessionIDTable\" containing non-ASCII characters, e.g. \"abc你好\" or any accented/cyrillic/emoji character, after PredefinedTable lookup did not match (custom tables are used verbatim).","commonSituations":"Users pasting 'random-looking' unicode strings as tables; configs saved in encodings that introduce smart quotes or BOM characters.","solutions":["Restrict \"sessionIDTable\" to ASCII bytes 0x00-0x7F (practically: alphanumeric plus URL-safe symbols)","Use a named predefined table from splithttp.PredefinedTable instead of a custom string","Re-save the config as plain UTF-8 without BOM/smart quotes"],"exampleFix":"// before\n\"sessionIDTable\": \"aàbçdé\"\n// after\n\"sessionIDTable\": \"abcdefghijklmnopqrstuvwxyz0123456789\"","handlingStrategy":"validation","validationCode":"// Go: ASCII-only table check before Build()\nfor i := 0; i < len(cfg.SessionIDTable); i++ {\n\tif cfg.SessionIDTable[i] >= 0x80 {\n\t\treturn errors.New(\"sessionIDTable must be 7-bit ASCII\")\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Restrict custom tables to alphanumeric + URL-safe ASCII","Save configs as plain UTF-8 without BOM or smart quotes"],"tags":["config","splithttp","session","ascii","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}