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

  1. Change the password field; the reseeded shuffle may avoid the empty grid.
  2. Verify you are on a released, consistent build of the transport.
  3. 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

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


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/8808d15149bc890e. Report an issue: GitHub.