XTLS/Xray-core · error
Invalid integer range, expected either string of form "1-2"
Error message
Invalid integer range, expected either string of form "1-2" or plain integer.
What it means
Thrown by Int32Range.UnmarshalJSON in infra/conf/common.go when the JSON value is neither a string that ParseRangeString can parse as 'left-right' nor a plain JSON integer. The code first tries the string form (including ranges), then a raw integer form; failure of both produces this message.
Source
Thrown at infra/conf/common.go:329
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (v *Int32Range) UnmarshalJSON(data []byte) error {
defer v.ensureOrder()
var str string
var rawint int32
if err := json.Unmarshal(data, &str); err == nil {
left, right, err := ParseRangeString(str)
if err == nil {
v.Left, v.Right = int32(left), int32(right)
return nil
}
} else if err := json.Unmarshal(data, &rawint); err == nil {
v.Left = rawint
v.Right = rawint
return nil
}
return errors.New("Invalid integer range, expected either string of form \"1-2\" or plain integer.")
}
// ensureOrder() gives value to .From & .To and make sure .From < .To
func (r *Int32Range) ensureOrder() {
r.From, r.To = r.Left, r.Right
if r.From > r.To {
r.From, r.To = r.To, r.From
}
}
// "-114-514" → ["-114","514"]
// "-1919--810" → ["-1919","-810"]
func splitFromSecondDash(s string) []string {
parts := strings.SplitN(s, "-", 3)
if len(parts) < 3 {
return []string{s}
}
return []string{parts[0] + "-" + parts[1], parts[2]}View on GitHub (pinned to 7d214f8b09)
Solutions
- Use a string range: "length": "100-200"
- Or a single integer which becomes both Left and Right: "length": 100
- Never use a JSON array or floating point for these fields
Example fix
// before "length": [100, 200] // after "length": "100-200"
Defensive patterns
Strategy: type-guard
Validate before calling
func validateInt32RangeJSON(raw []byte) error {
var i int32
if json.Unmarshal(raw, &i) == nil {
return nil
}
var s string
if json.Unmarshal(raw, &s) == nil {
if matched, _ := regexp.MatchString(`^-?\d+-(-)?\d+$|^\d+$`, s); matched {
return nil
}
}
return errors.New("expected integer or \"min-max\" string")
} Type guard
func isInt32Range(v any) bool {
switch t := v.(type) {
case float64:
return t == float64(int32(t))
case string:
_, _, err := conf.ParseRangeString(t) // or a local -?\d+-\d+ regex
return err == nil
}
return false
} Try / catch
if err := json.Unmarshal(data, &r); err != nil {
if strings.Contains(err.Error(), "Invalid integer range") {
return fmt.Errorf("field must be 100 or \"100-200\", not an array/float/null")
}
return err
} Prevention
- Never use [min,max] arrays for range fields
- Quote ranges; leave single values unquoted or quoted integers
When it happens
Trigger: Fields typed conf.Int32Range (e.g.Freedom strategy 'settings.frag' related length ranges in recent Xray, Mux 'xudp' unrelated) given values like "range": [1,2] (array), "range": "abc", "range": 1.5, or "range": null.
Common situations: Users assuming a two-element array [min,max] works (it does not — use a "min-max" string or a single int); quoting is required for ranges but not for single values; float values are rejected.
Related errors
- unknown format of a string list:
- invalid address:
- invalid fakedns config
- bridge tag is empty
- bridge domain is empty
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/bcc9f27aab8a0de9.
Report an issue: GitHub.