XTLS/Xray-core · critical
grid %d has no valid clue set
Error message
grid %d has no valid clue set
What it means
Thrown by buildTable when the password-seeded shuffle assigns byte b a grid index whose pattern list is empty (no valid clue set). Each of the 256 shuffled grids must carry at least one clue pattern; an empty one breaks encoding for that byte value. Internal invariant, but the assignment depends on the password seed.
Source
Thrown at transport/internet/finalmask/sudoku/table.go:407
for i := range order {
order[i] = i
}
hash := sha256.Sum256([]byte(password))
seed := int64(binary.BigEndian.Uint64(hash[:8]))
rng := rand.New(rand.NewSource(seed))
rng.Shuffle(len(order), func(i, j int) {
order[i], order[j] = order[j], order[i]
})
t := &table{
decode: make(map[uint32]byte, 1<<16),
layout: layout,
}
for b := 0; b < 256; b++ {
patList := patterns[order[b]]
if len(patList) == 0 {
return nil, fmt.Errorf("grid %d has no valid clue set", order[b])
}
enc := make([][4]byte, 0, len(patList))
for _, groups := range patList {
hints := [4]byte{
layout.encodeHint(groups[0]),
layout.encodeHint(groups[1]),
layout.encodeHint(groups[2]),
layout.encodeHint(groups[3]),
}
sortedHints := sort4(hints)
key := packKey(sortedHints)
if old, exists := t.decode[key]; exists && old != byte(b) {
return nil, fmt.Errorf("decode key collision for byte %d and %d", old, b)
}
t.decode[key] = byte(b)
enc = append(enc, hints)
}View on GitHub (pinned to 7d214f8b09)
Solutions
- Change the password field; the reseeded shuffle may avoid the empty grid.
- Verify you are on a released, consistent build of the transport.
- Report upstream with the password (if non-sensitive) and version if it persists.
Example fix
// before "password": "alpha" // after "password": "alpha2"
Defensive patterns
Strategy: retry
Try / catch
var t *table
for attempt := 0; attempt < 3; attempt++ {
var err error
t, err = buildTable(passwordWithAttemptSalt(attempt), layout)
if err == nil || !strings.Contains(err.Error(), "no valid clue set") {
break
}
} Prevention
- Since grid assignment is password-seeded, changing the password changes the outcome; keep configs reproducible.
- Report persistent occurrences upstream rather than working around them blindly.
When it happens
Trigger: A grid that survived the >=256 count check but has an empty per-grid pattern list for the specific password-derived shuffle order. Only reachable if upstream pattern generation produced a partially-filled entry.
Common situations: Custom or patched builds with modified pattern generation; not observed with stock binaries. Changing the password alters the shuffle and can mask or expose the condition.
Related errors
- not enough sudoku grids: %d
- customTable produced empty padding pool
- decode key collision for byte %d and %d
- grid %d has no uniquely decodable clue set
- invalid sudoku ascii mode: %s
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/8808d15149bc890e.
Report an issue: GitHub.