XTLS/Xray-core · error

last lengths entry min can't be 0

Error message

last lengths entry min can't be 0

What it means

FragmentMask.Build (infra/conf/transport_finalmask.go:276) requires the LAST fragment-length interval to have a non-zero minimum. LengthsMin entries (from c.Lengths[] or the single c.Length) define byte-size ranges per fragment; a final entry with min 0 would allow zero-length fragments at the end of the stream, so it is rejected.

Source

Thrown at infra/conf/transport_finalmask.go:276

		config.PacketsFrom = int64(from)
		config.PacketsTo = int64(to)
		if config.PacketsFrom == 0 {
			return nil, errors.New("PacketsFrom can't be 0")
		}
	}

	if len(c.Lengths) > 0 {
		for _, r := range c.Lengths {
			config.LengthsMin = append(config.LengthsMin, int64(r.From))
			config.LengthsMax = append(config.LengthsMax, int64(r.To))
		}
	} else {
		config.LengthsMin = append(config.LengthsMin, int64(c.Length.From))
		config.LengthsMax = append(config.LengthsMax, int64(c.Length.To))
	}

	if config.LengthsMin[len(config.LengthsMin)-1] == 0 {
		return nil, errors.New("last lengths entry min can't be 0")
	}

	if len(c.Delays) > 0 {
		for _, r := range c.Delays {
			config.DelaysMin = append(config.DelaysMin, int64(r.From))
			config.DelaysMax = append(config.DelaysMax, int64(r.To))
		}
	} else {
		config.DelaysMin = append(config.DelaysMin, int64(c.Delay.From))
		config.DelaysMax = append(config.DelaysMax, int64(c.Delay.To))
	}

	config.MaxSplitMin = int64(c.MaxSplit.From)
	config.MaxSplitMax = int64(c.MaxSplit.To)

	return config, nil
}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Give the last lengths entry from>=1, e.g. {"from":50,"to":100}
  2. If using a single length range, set "length":{"from":1,...} not from:0
  3. Move any {from:0} bucket to a non-final position

Example fix

// before
"lengths": [ {"from":100,"to":200}, {"from":0,"to":64} ]
// after
"lengths": [ {"from":100,"to":200}, {"from":8,"to":64} ]
Defensive patterns

Strategy: validation

Validate before calling

const lens = (cfg.lengths ?? [cfg.length]).filter(Boolean);
if (!lens.length) throw new Error('lengths/length required');
const last = lens[lens.length - 1];
if (last.from === 0) throw new Error('last lengths entry min must be >= 1');

Prevention

When it happens

Trigger: "lengths":[{"from":100,"to":200},{"from":0,"to":50}] or plain "length":{"from":0,...} when lengths is absent — the last (only) entry then has min 0. Only the final entry is checked; earlier entries with from:0 are allowed (zero-size padding mid-stream).

Common situations: Copy-pasting interval templates where the first entry is {"from":0,...} and then appending more; intending 0 to mean 'any size'; generators that always emit a terminal {0,x} catch-all bucket.

Related errors


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