{"record":{"id":"53425a82bfd72578","repo":"XTLS/Xray-core","slug":"customtable-must-be-8-chars-got-d","errorCode":null,"errorMessage":"customTable must be 8 chars, got %d","messagePattern":"customTable must be 8 chars, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/internet/finalmask/sudoku/table.go","lineNumber":182,"sourceCode":"\treturn pMin, pMax\n}\n\nfunc normalizeASCII(mode string) (string, error) {\n\tswitch strings.ToLower(strings.TrimSpace(mode)) {\n\tcase \"\", \"entropy\", \"prefer_entropy\":\n\t\treturn \"prefer_entropy\", nil\n\tcase \"ascii\", \"prefer_ascii\":\n\t\treturn \"prefer_ascii\", nil\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"invalid sudoku ascii mode: %s\", mode)\n\t}\n}\n\nfunc normalizeCustomTable(pattern string) (string, error) {\n\tcleaned := strings.ToLower(strings.TrimSpace(pattern))\n\tcleaned = strings.ReplaceAll(cleaned, \" \", \"\")\n\tif len(cleaned) != 8 {\n\t\treturn \"\", fmt.Errorf(\"customTable must be 8 chars, got %d\", len(cleaned))\n\t}\n\n\tvar xCount, pCount, vCount int\n\tfor _, ch := range cleaned {\n\t\tswitch ch {\n\t\tcase 'x':\n\t\t\txCount++\n\t\tcase 'p':\n\t\t\tpCount++\n\t\tcase 'v':\n\t\t\tvCount++\n\t\tdefault:\n\t\t\treturn \"\", fmt.Errorf(\"customTable has invalid char %q\", ch)\n\t\t}\n\t}\n\tif xCount != 2 || pCount != 2 || vCount != 4 {\n\t\treturn \"\", fmt.Errorf(\"customTable must contain exactly 2 x, 2 p and 4 v\")\n\t}","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/finalmask/sudoku/table.go#L164-L200","documentation":"Thrown by normalizeCustomTable when the customTable string, after lowercasing, trimming, and removing all spaces, is not exactly 8 characters long. The custom table describes a byte layout with 8 bit-slots, so any other length is rejected before a layout can be built.","triggerScenarios":"Configuring customTable with 7 or 9 characters, e.g. \"xxppvvv\" or \"xxppvvvvv\". Also triggered by patterns like \"xx pp vvvv\" (7 letters after space removal) or an empty string where a custom layout is expected.","commonSituations":"Miscounting the pattern characters when hand-writing the config; copying a pattern with a missing or extra character from docs or chat; assuming spaces count toward the 8 chars (they are stripped before the length check).","solutions":["Count the letters: the value must contain exactly 8 characters made of x, p, v (spaces allowed but ignored).","Use a canonical pattern such as \"xxppvvvv\".","Leave customTable empty to use the default entropy layout instead."],"exampleFix":"// before\n\"customTable\": \"xxppvvv\"\n// after\n\"customTable\": \"xxppvvvv\"","handlingStrategy":"validation","validationCode":"p := strings.ReplaceAll(strings.ToLower(strings.TrimSpace(cfg.CustomTable)), \" \", \"\")\nif p != \"\" && len(p) != 8 {\n\treturn fmt.Errorf(\"customTable must be 8 chars after trimming spaces, got %d\", len(p))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember spaces are stripped before the length check; count letters only.","Generate patterns programmatically from a fixed 8-slot template instead of hand-typing."],"tags":["config","validation","finalmask","sudoku"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}