XTLS/Xray-core · error
Interval must be at least 5
Error message
Interval must be at least 5
What it means
Range check on the UDP hop interval under finalMask.quicParams.udpHop.interval: a non-zero From or To below 5 is rejected (0 means unset and is allowed). Units follow the config schema (seconds). It exists to prevent hop intervals so short they would thrash connections.
Source
Thrown at infra/conf/transport_internet.go:257
return nil, errors.New("BrutalUp must be at least 65536 bytes per second")
}
if down > 0 && down < 65536 {
return nil, errors.New("BrutalDown must be at least 65536 bytes per second")
}
c.FinalMask.QuicParams.Congestion = strings.ToLower(c.FinalMask.QuicParams.Congestion)
switch c.FinalMask.QuicParams.Congestion {
case "", "brutal", "reno", "bbr":
case "force-brutal":
if up == 0 {
return nil, errors.New("force-brutal requires up")
}
default:
return nil, errors.New("unknown congestion control: ", c.FinalMask.QuicParams.Congestion, ", valid values: reno, bbr, brutal, force-brutal")
}
if (c.FinalMask.QuicParams.UdpHop.Interval.From != 0 && c.FinalMask.QuicParams.UdpHop.Interval.From < 5) || (c.FinalMask.QuicParams.UdpHop.Interval.To != 0 && c.FinalMask.QuicParams.UdpHop.Interval.To < 5) {
return nil, errors.New("Interval must be at least 5")
}
if c.FinalMask.QuicParams.InitStreamReceiveWindow > 0 && c.FinalMask.QuicParams.InitStreamReceiveWindow < 16384 {
return nil, errors.New("InitStreamReceiveWindow must be at least 16384")
}
if c.FinalMask.QuicParams.MaxStreamReceiveWindow > 0 && c.FinalMask.QuicParams.MaxStreamReceiveWindow < 16384 {
return nil, errors.New("MaxStreamReceiveWindow must be at least 16384")
}
if c.FinalMask.QuicParams.InitConnectionReceiveWindow > 0 && c.FinalMask.QuicParams.InitConnectionReceiveWindow < 16384 {
return nil, errors.New("InitConnectionReceiveWindow must be at least 16384")
}
if c.FinalMask.QuicParams.MaxConnectionReceiveWindow > 0 && c.FinalMask.QuicParams.MaxConnectionReceiveWindow < 16384 {
return nil, errors.New("MaxConnectionReceiveWindow must be at least 16384")
}
if c.FinalMask.QuicParams.MaxIdleTimeout != 0 && (c.FinalMask.QuicParams.MaxIdleTimeout < 4 || c.FinalMask.QuicParams.MaxIdleTimeout > 120) {
return nil, errors.New("MaxIdleTimeout must be between 4 and 120")
}
if c.FinalMask.QuicParams.KeepAlivePeriod != 0 && (c.FinalMask.QuicParams.KeepAlivePeriod < 2 || c.FinalMask.QuicParams.KeepAlivePeriod > 60) {View on GitHub (pinned to 7d214f8b09)
Solutions
- Raise both from and to to at least 5 (or remove them for the default).
- Keep from <= to so the range is meaningful.
- Confirm the field's unit in the config docs before tuning.
Example fix
// before
"udpHop": { "interval": { "from": 1, "to": 3 } }
// after
"udpHop": { "interval": { "from": 5, "to": 10 } } Defensive patterns
Strategy: validation
Validate before calling
func udpHopIntervalOK(qp map[string]any) bool {
uh, _ := qp["udpHop"].(map[string]any)
iv, _ := uh["interval"].(map[string]any)
for _, k := range []string{"from", "to"} {
if v, ok := iv[k].(float64); ok && v != 0 && v < 5 { return false }
}
return true
} Prevention
- Clamp the interval UI/schema to a minimum of 5.
- Confirm units (seconds) before tuning.
- Keep 0 as the sentinel for 'unset' rather than using tiny non-zero values.
When it happens
Trigger: "udpHop": { "interval": { "from": 2 } } or any non-zero endpoint below 5.
Common situations: Tuning hop intervals down for faster rotation without knowing the floor; setting milliseconds where seconds are expected (making values tiny); copying aggressive values from other tools.
Related errors
- unknown bbr profile
- BrutalUp must be at least 65536 bytes per second
- BrutalDown must be at least 65536 bytes per second
- force-brutal requires up
- unknown congestion control: + c.FinalMask.QuicParams.Conges
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/99916c8181692de3.
Report an issue: GitHub.