XTLS/Xray-core · error
variant %d has no chunks
Error message
variant %d has no chunks
What it means
When a paddingTurn uses variants, each variant must contain at least one chunk defining its record layout; this error names the variant index whose chunks slice is empty. An empty variant has no length and no delays, so bounds computation and framing would be undefined.
Source
Thrown at transport/internet/finalmask/xmc/padding.go:336
return chunks
}
func paddingTurnBounds(turn paddingTurn) (int, int, error) {
if len(turn.variants) == 0 {
if turn.minLength < 1 || turn.maxLength < turn.minLength || turn.maxLength > maxPaddingTurnLength {
return 0, 0, fmt.Errorf("invalid range: %d-%d", turn.minLength, turn.maxLength)
}
return turn.minLength, turn.maxLength, nil
}
if turn.minLength != 0 || turn.maxLength != 0 {
return 0, 0, fmt.Errorf("variants cannot be combined with a length range")
}
minLength := maxPaddingTurnLength + 1
maxLength := 0
for i, variant := range turn.variants {
if len(variant.chunks) == 0 {
return 0, 0, fmt.Errorf("variant %d has no chunks", i)
}
if len(variant.delays) != 0 && len(variant.delays) != len(variant.chunks) {
return 0, 0, fmt.Errorf("variant %d has %d chunks and %d delays", i, len(variant.chunks), len(variant.delays))
}
for j, chunkLength := range variant.chunks {
if chunkLength < 1 || chunkLength > maxPaddingChunkLength {
return 0, 0, fmt.Errorf("variant %d chunk %d has invalid length: %d", i, j, chunkLength)
}
if len(variant.delays) > 0 {
if err := validatePaddingDelayRange(variant.delays[j]); err != nil {
return 0, 0, fmt.Errorf("variant %d chunk %d has an invalid delay: %w", i, j, err)
}
}
}
length := paddingVariantLength(variant)
if length > maxPaddingTurnLength {
return 0, 0, fmt.Errorf("variant %d is too long: %d", i, length)
}View on GitHub (pinned to 7d214f8b09)
Solutions
- Give every variant at least one chunk of length 1..49152 (maxPaddingChunkLength).
- Filter out empty variants before building the schedule.
- Add a config-side check: reject padding entries with an empty chunks array at load time.
Example fix
// before
variants = append(variants, paddingVariant{})
// after
variants = append(variants, paddingVariant{chunks: []int{256}}) Defensive patterns
Strategy: validation
Validate before calling
for i, v := range turn.variants {
if len(v.chunks) == 0 {
return fmt.Errorf("variant %d empty", i)
}
} Prevention
- Filter empty variant entries before schedule construction.
- Validate chunk lengths (1..49152) in the same pass.
- Reject empty chunks arrays in user-facing config parsing.
When it happens
Trigger: Appending paddingVariant{} or a variant built from an empty []int to turn.variants; programmatic variant construction where a loop accidentally appends the zero value.
Common situations: Generating variants from user config where an empty chunk list passes through unvalidated; refactoring presets and leaving a placeholder empty variant behind.
Related errors
- invalid range: %d-%d
- variants cannot be combined with a length range
- empty padding schedule
- negative first turn prefix length: %d
- first prefixed padding turn is not client-to-server
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/7587e6cef25f03ce.
Report an issue: GitHub.